Compare commits

...

590 Commits

Author SHA1 Message Date
rocky
e85eabcfd6 Remove setuptools pin 2025-07-29 09:44:37 -04:00
R. Bernstein
1fb05c2e91 Update README.rst 2025-07-09 11:40:29 -04:00
rocky
ccc12ea417 Add BlackHat Asia 2024 link 2025-07-09 11:36:03 -04:00
R. Bernstein
5e819f5157 Merge pull request #514 from willschlitzer/copyright-date-fix
Change copyright year to 2018
2025-06-08 07:42:23 -04:00
R. Bernstein
9067d50f00 Merge pull request #515 from willschlitzer/typo-fix-codefns
Fix typo for code_fns function docstring
2025-06-08 07:41:57 -04:00
Will Schlitzer
3b982d4883 Fix typo for function docstring 2025-06-07 23:01:53 -04:00
Will Schlitzer
2ba8bf13f7 Change copyright year to 2018 2025-06-07 22:53:48 -04:00
rocky
521c983b51 Administrivia 2024-12-21 02:31:09 -05:00
rocky
7ca4363602 Administrivia 2024-12-12 18:03:31 -05:00
rocky
b2cf041ec3 Remove unused import 2024-12-02 19:39:56 -05:00
R. Bernstein
5e6fad210f Merge pull request #507 from c10udlnk/master
Fix when parsing NOP
2024-12-01 15:13:25 -05:00
c10udlnk
efd28710ce Add NOP test cases
Add test cases for check NOP opcode
2024-12-01 16:22:54 +08:00
c10udlnk
f72b2c1153 Fix when parsing NOP
Fix error when parsing NOP opcode
2024-11-29 11:03:13 +08:00
rocky
e4e3743de5 Tweak when we delete LOAD_CONST RETURN_VALUE 2024-11-28 08:03:32 -05:00
rocky
74b39e2262 Administriva 2024-11-28 07:29:37 -05:00
rocky
4ac5564df3 Don't remove LOAD_CONST RETURN_VALUE when...
the LOAD_CONST has a non-None value, or the LOAD_CONST
has a line associated with it.
2024-11-28 07:27:13 -05:00
rocky
addddf82f5 Correct getting code node on mkfunc 2024-11-26 09:44:49 -05:00
rocky
f4d21d36e5 Add BlackHat Asia 2024 and update CircleCI link 2024-11-19 15:33:20 -05:00
rocky
9f915384ce Bump spark_parser version allowed 2024-11-15 19:45:29 -05:00
R. Bernstein
2786cbcb89 Merge pull request #504 from rocky/TABLE_DIRECT-pollution
Don't update global tables, copy them instead.
2024-11-12 16:38:40 -05:00
rocky
5c391f9101 Update CircleCI 2024-11-12 16:35:36 -05:00
R. Bernstein
f4becb42e4 Merge pull request #505 from gdesmar/use_single_table_copy
Use a single TABLE copy
2024-11-12 16:17:59 -05:00
gdesmar
cf34014766 Use a single TABLE copy 2024-11-12 19:42:17 +00:00
rocky
37f38e45e1 Don't update global tables...
Work off of copies of them instead. Issue #503
2024-11-09 11:57:11 -05:00
rocky
ab7980374d Allow for newer spark-parser 2024-11-09 06:37:59 -05:00
rocky
9b38760173 Administrivia 2024-11-09 06:02:33 -05:00
R. Bernstein
27c869b69a Merge pull request #502 from gdesmar/docstring_bytes
Fix for print_docstring()'s `docstring.find(quote)` Type error
2024-10-16 20:31:12 -04:00
gdesmar
7db6a272af Adding tests for bytestring docstring 2024-10-16 20:19:39 +00:00
gdesmar
20d0a60550 Remove duplicate code of print_docstring 2024-10-10 20:24:56 +00:00
rocky
193c262ffb Administrivia
Folloow branching of other projects in this ilk
2024-10-09 04:00:14 -04:00
rocky
f0e1a7beba Try unpinning setuptools 2024-10-08 17:09:07 -04:00
rocky
eb088a84c8 Accept newer python-spark 2024-10-08 16:46:42 -04:00
gdesmar
4cd10b79e2 Convert docstring from bytes to str 2024-10-08 13:48:39 +00:00
rocky
f603a44cf7 Allow newer spark-parser 2024-10-07 11:09:46 -04:00
rocky
80d58f882a Track branch changes in python-spark 2024-10-04 04:46:26 -04:00
rocky
710167b806 Adminsitrivia 2024-09-21 07:29:12 -04:00
rocky
ff192ea6c1 Administrivia 2024-09-21 07:25:44 -04:00
rocky
c309730748 Note version of setuptools working on Python 3.6 2024-09-20 16:23:18 -04:00
rocky
e6c63e419e Administrivia 2024-09-20 16:17:07 -04:00
rocky
a878a74a12 Fixes #501 2024-08-27 11:21:56 -04:00
rocky
f82caba70f Administrivia 2024-07-22 18:31:59 -04:00
rocky
7dacd509a8 Administrivia 2024-07-22 17:57:50 -04:00
rocky
e6ddaab691 Adminstiriva: bump to dev0 version 2024-07-22 05:16:10 -04:00
rocky
f9b20f6eda Get ready for release 3.9.2 2024-07-21 18:56:22 -04:00
rocky
b0dd7f57c6 Lint 2024-07-21 18:36:12 -04:00
rocky
1a3f2b8ab0 Misc lint 2024-07-21 17:34:06 -04:00
rocky
5580b2b795 Bump min xdis version 2024-07-21 12:53:34 -04:00
rocky
aced47a020 Sync with 2.4 branch 2024-07-20 02:28:18 -04:00
rocky
ce690f3586 Lint initialization 2024-07-18 19:30:47 -04:00
rocky
25675f216f Sync fragments with pysource (a little bit) 2024-07-18 10:20:55 -04:00
rocky
915ff5e59c Remove pre 3.5 BUILD_MAP customiztion...
it is not needed here.
2024-07-15 13:53:36 -04:00
rocky
81922bdb23 Handle long dict litereals in 3.4- better...
Bracket in pseudo op COLLECTION_START ... BUILD_xx
2024-07-15 10:01:32 -04:00
rocky
d731d32c11 Simplify BREAK_LOOP detection...
by making more us of linestart. At least for now...
2024-07-14 14:45:25 -04:00
rocky
04da2fb8df Improve 3.4 ifelse inside a lambda
Fixes #426
2024-07-13 22:46:31 -04:00
rocky
389fc2360a 3.6 bug related to large whilestmt 2024-07-13 21:42:49 -04:00
rocky
7787166ddf Add grammar rule involving RETURN_END_IF 2024-07-13 17:47:21 -04:00
rocky
e3579463ab Loosen what is allowed in whilestmt38...
Fixes #498
2024-07-13 11:58:27 -04:00
rocky
0627215e98 BUILD_MAP is different pre 3.5 2024-07-13 09:51:49 -04:00
rocky
d0dc879b37 Note that we can now use xdis a little more 2024-07-13 07:25:36 -04:00
rocky
b28f3058fc Expand grammar check for ifelse continue for 2.7 2024-07-12 21:30:46 -04:00
rocky
703716ca6f Pick up recewnt try/except change from 2.5 2024-07-12 19:07:29 -04:00
rocky
14993d0af4 Add one more docstring 2024-07-12 14:48:07 -04:00
rocky
ad621efb7a Merge 2024-07-12 14:16:04 -04:00
rocky
cb2b90a94f Python 2.5 try/except reduce fix
Start getting aligner up to date
2024-07-12 14:15:04 -04:00
rocky
efbd6570b0 Update readmes 2024-07-12 13:02:45 -04:00
rocky
a42bef12d2 Remove a false negative test for try/except in 25 2024-07-12 12:39:27 -04:00
rocky
9d150e0707 Update copyright 2024-07-12 12:10:31 -04:00
rocky
f030b3316c Fix some 2.5 parsing bugs 2024-07-12 11:21:48 -04:00
rocky
9450165109 Add if/then rule to assist 2.5 parsing 2024-07-12 10:17:05 -04:00
rocky
be825239c6 2.6 custom tryelse code is no longer needed?
If it turns out to be needed, add it back in a better way.
2024-07-12 08:37:05 -04:00
rocky
4394d46f64 Remove redundant list_comp() fn 2024-07-11 20:16:03 -04:00
rocky
b10dd0ea5b 2.6 bug appears in 2.4 and 2.5 2024-07-11 18:52:09 -04:00
rocky
6fe8a1d2ba Address long-standing Python 2.6 try/except bug
Fixes #405
2024-07-11 14:01:50 -04:00
rocky
b0b67e9f34 Fix some 2.6 bytecode bugs
scanner26: disassemble interface has changed
make_function2: was missing ParserError2 import
2024-07-11 12:06:52 -04:00
rocky
3c6e378cc4 Spelling corrections 2024-07-10 13:31:39 -04:00
rocky
51141ad06d Use set literals 2024-06-03 07:55:44 -04:00
rocky
acdf777a35 Sync with decompile3 2024-06-03 07:39:13 -04:00
rocky
404c46c6bb Better const key sorting 2024-06-03 07:18:37 -04:00
rocky
0b9a3c668c Remove workflows 3.7 CI testing
3.7 no longer is available on github workflows
2024-05-30 05:03:00 -04:00
rocky
6f2a837765 Better sorting of TABLE_DIRECT keys 2024-05-30 04:35:58 -04:00
rocky
39b4b83977 Small set literal change 2024-05-07 11:33:03 -04:00
rocky
458d4727dd Properly escape strings.
Backported from decompyle3
2024-03-25 06:42:06 -04:00
rocky
3b1d5bddd9 Correct name in docstring 2024-03-17 21:29:48 -04:00
rocky
b6b76d9b81 Keep pre-toml setup around for a little while 2024-03-16 03:49:17 -04:00
rocky
29edaaed0e Get ready for release 3.9.1 2024-03-16 03:07:28 -04:00
rocky
bec88e4aaa Name phases "disassembly" and "tokenization" 2024-03-14 15:31:53 -04:00
rocky
b88af23406 Mis spelling corrections 2024-03-14 05:39:30 -04:00
rocky
daf54d2740 2.6 scanner show -A headers now 2024-03-13 21:39:35 -04:00
rocky
bf59e3c65e Small variable name fix 2024-03-13 21:08:08 -04:00
rocky
628b18fce7 rename assembly phases and tweak a err msg...
before tokenization -> disassembly
after tokenization -> tokenization
2024-03-13 21:02:27 -04:00
R. Bernstein
e6ff6033cf Merge pull request #489 from rocky/withasstmt-to-with_as
withasstmt -> with_as
2024-03-08 04:12:55 -05:00
rocky
156188f8bb withasstmt -> with_as
This matches Python's AST naamae better. Some linting and
sorting of dictionary keys done as well.
2024-03-08 04:10:33 -05:00
R. Bernstein
3724e02183 Merge pull request #488 from rocky/with-as-with-pass
Add context manager test...
2024-03-07 18:53:14 -05:00
rocky
8542df4639 Add context manager test...
handle degenerate 3.8 withas
2024-03-07 18:08:07 -05:00
R. Bernstein
b5c4e4b28b Merge pull request #487 from rocky/withasstmt-no-parens
simplify withas (for now)
2024-03-06 17:41:42 -05:00
rocky
f1169af582 simplify withas (for now) 2024-03-06 17:19:57 -05:00
rocky
33f49849f5 Add some 3.3 and 3.4 stdlib tests back in 2024-03-02 12:02:40 -05:00
rocky
c499d0a60a Fix in 3.3 subclass detection in class closures 2024-03-02 11:54:11 -05:00
rocky
d2d4367dae Add 3.3 bytecode testing..
Also, correct ifelse detection in 3.3
2024-03-02 07:01:40 -05:00
rocky
c591f4e6e6 Administrivia 2024-03-02 05:18:56 -05:00
rocky
69c5d463e6 Add liberapay name 2024-03-02 04:59:20 -05:00
rocky
830a2ebf44 Sync with decompyle3 2024-03-02 04:32:26 -05:00
rocky
e3be41164e Add pop return check from decompyle3 2024-02-25 08:34:13 -05:00
rocky
08009f9fc7 improve list comprehensions 2024-02-25 08:19:18 -05:00
rocky
d3ed646a8e Make a pass over 3.2 stdlib exclusions 2024-02-25 06:41:25 -05:00
rocky
d9ff58391f Admnistrivia 2024-02-25 06:11:50 -05:00
rocky
2b8406e7a8 mark "psuedo ops" 2024-02-25 06:08:06 -05:00
rocky
4a50de38e4 sync with other versions 2024-02-24 18:31:57 -05:00
rocky
9fd139a41d changes from other branches 2024-02-24 18:26:37 -05:00
rocky
8a1fd7e127 Keep optype info in token...
It is useful for ADD_VALUE
2024-02-24 17:41:32 -05:00
rocky
d2a171609e Remove messed-up show_tree call 2024-02-24 12:56:30 -05:00
rocky
76039a229d Go over 2.6 excludes 2024-02-24 12:12:06 -05:00
rocky
27dfb956d5 Administrivia 2024-02-24 10:26:45 -05:00
rocky
6d4d3df659 Administrivia 2024-02-24 10:26:02 -05:00
rocky
5a367717fa Merge hell 2024-02-24 10:14:31 -05:00
rocky
1ef631dd76 Track change in xdis Instruction ...
we now need to set positions which will be used in newer Pythons.
2024-02-18 21:13:30 -05:00
rocky
3e00880c1b remove double-quote preference here....
it is now done in xdis which is where it is better done
2024-02-18 08:21:07 -05:00
rocky
40c4764492 prefer string double quote, yet again. 2024-02-17 20:37:12 -05:00
rocky
8c3143ce4c Sync with decompyle3 2024-02-17 20:14:30 -05:00
rocky
0a08b8d3fc Simplify double quote preference in string 2024-02-17 19:46:57 -05:00
rocky
9f9f6de983 Administrivia
Don't use finish in sourced admin programs
2024-02-17 15:14:51 -05:00
rocky
f94100d24c sync with decompile3 2024-02-17 15:09:00 -05:00
rocky
3ef4ab4944 Prefer using double quote for strings 2024-02-17 12:57:48 -05:00
rocky
60ca6f485b More administrivia 2024-02-12 09:06:57 -05:00
rocky
05ebaf9ec1 More administrivia 2024-02-12 08:46:16 -05:00
rocky
e73cd749e7 More administrivia -
go over git branch checkout programs
2024-02-12 08:16:13 -05:00
rocky
02ed25e7cb Bugs found in 3.0 decomplation...
parsers/parse30.py; fix set comprehension grammar bug
uncompyle6/semantics/n_actions.py: evidence of the evils of modifying node data (via node.pop)
2024-02-12 00:58:42 -05:00
R. Bernstein
ca04ae98f7 Merge pull request #483 from rocky/xdis-fix-woes
Xdis fix woes
2024-02-11 23:28:43 -05:00
rocky
2886d2bd08 Track important changes to xdis
Annotation counts have changed.
EXTENDED_ARGS adjustment in instructions have been corrected.
2024-02-11 23:24:19 -05:00
rocky
8348d86b09 Better annotation parsing for < 3.6 2024-02-11 19:46:13 -05:00
rocky
454fac4adb Handle 3.3 MAKE_FUNCTION annotation args properly 2024-02-11 11:50:25 -05:00
rocky
147155e1d5 Administrivia:
automate merging
2024-02-11 08:42:32 -05:00
rocky
f1bf86088e Sync with decompyle3 2024-02-10 21:06:05 -05:00
rocky
c8b92e2275 Add needed newline separating abstract tree 2024-02-10 20:04:18 -05:00
rocky
5d8c40358e showtree workaround until we have better sync..
with decompyle3
2024-02-10 16:29:59 -05:00
rocky
dd8ee1466d Redo uncompyel6 options ...
Use click now and make more like decompyle3
2024-02-10 13:24:09 -05:00
R. Bernstein
d7a1d5bbad Merge pull request #482 from rocky/sync-with-decompile3
Sync with decompile3
2024-02-05 17:10:13 -05:00
rocky
61105840af Sync with decompyle3 2024-02-05 17:06:47 -05:00
rocky
f605f859ae Partial sync with decompyle3 2024-02-05 16:57:59 -05:00
rocky
33bc80bb24 f-string convert a file 2024-02-05 16:26:59 -05:00
rocky
86e22bbacb One more 2024-02-05 16:20:15 -05:00
rocky
f7436a4ff2 More lint 2024-02-05 16:17:48 -05:00
rocky
42ed183dbb Fix imports 2024-02-04 12:36:08 -05:00
rocky
e65a2db971 Small tweak 2024-02-03 18:40:38 -05:00
rocky
9f9074c285 Add a type annotation 2024-02-03 15:43:07 -05:00
rocky
9772454a3b Sync fragments with decompyle3 2024-02-03 15:28:48 -05:00
rocky
f7caf9b675 Remove strayh blank line 2024-02-03 15:15:55 -05:00
rocky
5f29d14608 Fix --linemap option, yet again. 2024-02-03 15:08:58 -05:00
rocky
db6c7159f8 lint 2024-02-03 14:47:08 -05:00
rocky
9839cfe93b Add pre-commit hook 2024-02-03 12:44:30 -05:00
rocky
d249c522a7 Fix up linemap option 2024-02-03 12:37:48 -05:00
R. Bernstein
675206911a Merge pull request #480 from jwilk-forks/spelling
Fix typos
2024-01-19 18:16:30 -05:00
Jakub Wilk
7a2348e4cc Fix typos 2024-01-19 23:20:13 +01:00
rocky
dcc9d1a571 Fix spelling via "codespell" 2023-12-17 10:52:32 -05:00
R. Bernstein
e9120eab45 Update HOW-TO-REPORT-A-BUG.md
grammar typo
2023-10-14 18:38:21 -04:00
rocky
77d727541b Note -F -extended in pydisasm 2023-10-10 09:20:18 -04:00
rocky
0ea75cadca Small bit of linting 2023-10-06 02:44:41 -04:00
rocky
0c18d35043 Bump python master version default 2023-09-29 22:08:28 -04:00
rocky
34ef91312e Revise to not zip attachment expected 2023-09-03 09:36:06 -04:00
rocky
803678e9b4 Track recent xdis changes 2023-08-26 14:39:42 -04:00
rocky
20c58e2e2a Small semantic action acceptance change 2023-08-26 14:15:23 -04:00
rocky
9829e04611 Bug in collection printing ...
`"%s" % value` can fail if value is a tuple
2023-08-17 19:35:08 -04:00
R. Bernstein
c58e6efa3d Merge pull request #471 from rocky/add-ending_return
Simpilfy grammar via ending_return
2023-08-13 07:56:33 -04:00
rocky
c0957d956f Simpilfy grammar via ending_return 2023-08-13 07:50:13 -04:00
rocky
b3ddf95d7a comprehension in lambda for 3.0 & 3.1 2023-08-12 07:12:10 -04:00
R. Bernstein
9a14d2dea8 Merge pull request #470 from rocky/comprehension-in-lambda-parsing-bug
Handle comprehensions inside a lambda
2023-08-12 06:38:28 -04:00
rocky
20af515dda Handle comprehensions inside a lambda 2023-08-11 12:13:46 -04:00
R. Bernstein
48a0a411b8 Merge pull request #468 from rocky/ifstmt-reduce-check-bug
Fixes #467
2023-08-09 05:39:23 -04:00
rocky
8865599145 Fixes #467 2023-08-09 04:48:42 -04:00
rocky
3a178836a6 Fix a small default-value bug 2023-07-29 13:00:21 -04:00
R. Bernstein
2ff80c040c Merge pull request #465 from rocky/chained-compare-rename
Chained compare rename
2023-07-29 12:15:25 -04:00
rocky
ddeb5af6d6 compare_chained2 _> compare_chained_right 2023-07-29 12:09:25 -04:00
rocky
843e3585e2 chained-compare1 -> chained-compare-middle 2023-07-29 12:01:14 -04:00
rocky
ea76de02bd Tweak bug-report 2023-07-07 10:13:14 -04:00
rocky
3a8f3e550d Include xdis version in bug report 2023-07-05 07:59:04 -04:00
rocky
227f494fa8 Double -a option show asm before tokenization 2023-07-04 07:13:54 -04:00
rocky
99f054ea9d Forgot to include 3.3 in recent generator fix 2023-07-01 23:22:57 -04:00
rocky
d6608712f1 correct fn name on older 3.x cross decompile...
Also black, lint, and isort some
2023-06-30 20:30:06 -04:00
rocky
dc286b91c8 pip woes 2023-06-30 16:46:03 -04:00
rocky
120b66b89e Try Python 3.8 as base image 2023-06-30 16:41:32 -04:00
rocky
1c28bc1c82 Update Python version and exdis version 2023-06-30 16:38:43 -04:00
R. Bernstein
3f21b2a115 Update build to large resource class in config.yml 2023-06-30 16:34:55 -04:00
rocky
4b296e1ead Correct generator function parsing for 3.3..3.5 2023-06-30 15:43:27 -04:00
rocky
828b1c989d Fix fragment bugs
mostly with respect to show_ast handling
2023-06-29 15:56:53 -04:00
rocky
568b64b59e Allow decompilation of older bytecode from 3.9+ 2023-06-16 07:30:25 -04:00
rocky
36f00d334e Revert last change. 2023-06-16 07:10:37 -04:00
rocky
b0086460de Exit when version is not supported 2023-06-15 21:32:17 -04:00
rocky
41d26bde79 Lint some files 2023-05-29 11:00:44 -04:00
rocky
ebcc12e2c3 Misc lint things 2023-05-29 10:36:50 -04:00
rocky
286bb5948c Go over bug-report template 2023-04-30 22:19:27 -04:00
rocky
c01ab5e001 Tweaks to long-literal handling...
* Use version tuple comparison for version testing
* small lintin of n_actions
* revise test so assert is not removed in 3.8
2023-04-19 02:08:36 -04:00
R. Bernstein
6f3fe06594 Merge pull request #452 from andrem-eberle/master
Proposed fix for the extra quotes
2023-04-19 02:01:45 -04:00
Andre Eberle
54776275c0 Modified n_actions.py to issue __repr__ on py2 and __str__ py3, should fix the extra quotes 2023-04-18 00:12:00 -04:00
rocky
22373b4195 Update 2.5 stdlib excludes 2023-04-17 23:35:00 -04:00
rocky
9746b21bbf Update 2.7 literal test 2023-04-17 23:20:42 -04:00
R. Bernstein
2f650a6969 Merge pull request #451 from andrem-eberle/master
Tentative fix for #439
2023-04-17 19:32:33 -04:00
Andre Eberle
4d420e2e37 Typo in comments 2023-04-17 19:26:35 -04:00
Andre Eberle
d1ef91dd49 Added tests for issue #439, global/const issues 2023-04-17 19:20:37 -04:00
Andre Eberle
3314c0d222 Fix to the ADD_VALUE_x opcodes 2023-04-17 18:53:51 -04:00
R. Bernstein
3d5e2201d2 Merge pull request #449 from rocky/correct-aboslute-import-and-docstring
Correct a couple of bugs...
2023-04-17 16:45:31 -04:00
rocky
7ad0c37c62 Correct a couple of bugs...
We weren't distinguising relative imports from absolute imports.
Fixes #444

Picking out docstring was broken too.
2023-04-17 16:35:27 -04:00
R. Bernstein
b6aa58790f Merge pull request #446 from rocky/do-not-quote-non-str-args
Use xdis pattr extraction for LOAD_NAME
2023-04-16 15:47:53 -04:00
rocky
ad00b9a4ee Use xdis pattr extraction for LOAD_NAME 2023-04-15 07:31:35 -04:00
rocky
551e428086 Go over stdlib test for 2.{6,7} 2023-04-08 22:10:21 -04:00
R. Bernstein
cd0049933f Merge pull request #440 from andrem-eberle/master
Tentative fix for issue #437.
2023-04-08 20:37:31 -04:00
Andre Eberle
7f3c1fa3a4 Tentative fix for issue #437. I added a new set of rules in ifelsestmt.py to check against for offsets. Seems to have fixed current issue. The result output is switching nested if-else-if-else-etc to a chain of if-elif-elif now, but semantically seems correct. 2023-04-08 16:54:55 -04:00
rocky
f76c35c902 Slightly nicer docstring detection for closure 2023-03-25 02:20:26 -04:00
rocky
82963cdf2c Preserve docstring in closures..
This change synchronized from decompyle3
2023-03-24 20:31:49 -04:00
rocky
a20972dd12 xdis PYTHON_VERSION removal 2023-02-26 19:29:08 -05:00
rocky
18b5934b2d Allow xdis 6.1.0 2023-02-26 19:21:30 -05:00
R. Bernstein
982abe0980 Merge pull request #430 from rocky/sync-with-decompyle3
Synch with decompyle3 code a little bit
2023-01-19 05:10:20 -05:00
rocky
41d1ba31f3 Synch with decompyle3 code a little bit 2023-01-19 04:31:19 -05:00
rocky
e03f4cfe43 Try adding no blank templates 2023-01-18 22:23:06 -05:00
R. Bernstein
53a5e03a8f Merge pull request #429 from rocky/reinstate-pos-args
Reinstate pos_args in CALL_METHOD
2023-01-18 21:23:23 -05:00
rocky
7c99564640 Reinstate pos_args in CALL_METHOD 2023-01-18 21:01:11 -05:00
rocky
931abc5726 self.opc.version -> self.opc.version_tuple
The next release of xdis will no longer support self.opc.version (a
float value which doesn't work in the presense of 3.10 and above)
2023-01-18 17:08:39 -05:00
rocky
2b3cd696db 3.0 set comprehension bug 2023-01-16 03:50:50 -05:00
rocky
50697bb79e Improve set comprehension for Python 3.0 2023-01-16 03:40:55 -05:00
R. Bernstein
137dd64a46 Merge pull request #427 from rocky/make-fn-or-closure-with-annotatation
try to be more honest about MAKE_{FUNCTION,CLOSURE}
2023-01-16 02:12:13 -05:00
rocky
9a7eb0ad0a try to be more honest about MAKE_{FUNCTION,CLOSURE} 2023-01-16 01:45:37 -05:00
rocky
154dabfcef Handle Python 3.4 MAKE_CLOSURE fns ...
Is done just like Python 3.3
2023-01-14 09:54:48 -05:00
rocky
42d26ccbd7 Bump version 2023-01-14 06:21:12 -05:00
rocky
73a4c0be78 Use 3.7.16 for master version 2023-01-14 02:49:43 -05:00
rocky
92830c2eae Newer setuptools 2023-01-14 02:22:53 -05:00
rocky
090570cd34 3.4-3.5 MAKE_CLOSURE with annotate
Docs lie about annnotation args. Slight adjustment here.
More is probably needed.
2023-01-14 02:20:59 -05:00
rocky
16914feb12 Get ready for release 3.9.0 2022-12-22 23:57:31 -05:00
rocky
1ffc58ac6d Bump list of newest versions 2022-12-22 22:44:30 -05:00
rocky
77bbe49c32 Change Python versions used in testing
to match what works on workflows CI
2022-12-20 10:27:11 -05:00
rocky
e8d4d383c6 pycharm lint, isort & black 2022-12-01 17:36:00 -05:00
rocky
9f1514a2dd Update copyrights 2022-11-27 05:18:45 -05:00
rocky
6110b3a095 Add isort configuration 2022-11-27 04:50:27 -05:00
rocky
d1911d2487 More lint 2022-11-27 04:14:46 -05:00
rocky
55bb5640ee More lint 2022-11-27 03:52:43 -05:00
rocky
cab53b49b5 Small grammar and spelling errors 2022-11-27 03:25:55 -05:00
rocky
514b0d0b0c Sync from decompyle3 2022-11-06 01:24:28 -05:00
R. Bernstein
283e493270 Merge pull request #419 from jameshilliard/token-opc
Replace remaining self.opc with token.opc
2022-11-05 20:59:47 -04:00
James Hilliard
e08324d85c Replace remaining self.opc with token.opc 2022-11-05 19:39:31 -04:00
R. Bernstein
03282d3dd9 Merge pull request #418 from jameshilliard/fix-status-msg
Fix status_msg args
2022-11-05 19:23:35 -04:00
rocky
207dc0b506 opc field in while1 reduction is off of token...
not self (parse)
2022-11-05 19:20:16 -04:00
James Hilliard
6787a582cf Fix status_msg args
Fixes:
uncompyle6/bin/uncompile.py", line 201, in main_bin
    mess = status_msg(do_verify, *result)
TypeError: status_msg() takes 5 positional arguments but 6 were given
2022-11-05 18:59:13 -04:00
R. Bernstein
647df7140c Merge pull request #416 from jameshilliard/fix-parsers-version
Fix ImportError: cannot import name PYTHON_VERSION
2022-11-05 18:35:30 -04:00
James Hilliard
ab508e1ec9 Fix ImportError: cannot import name PYTHON_VERSION 2022-11-05 17:17:24 -04:00
rocky
8843686b49 Add generator expression Python 3.0 .. 3.2 2022-11-05 10:31:00 -04:00
rocky
9d1cf50c5e Add generator expression Python 3.0 .. 3.2 2022-11-05 10:15:45 -04:00
rocky
98626ee162 Misc linting 2022-11-05 05:04:25 -04:00
R. Bernstein
2884068c61 Merge pull request #415 from jameshilliard/parsererror2
Add missing ParserError2 in make_functions36
2022-11-05 01:09:05 -04:00
rocky
57d2386cc3 Fix another 3.0 list comprehension parse 2022-11-05 00:27:05 -04:00
James Hilliard
ce66b12176 Add missing ParserError2 in make_functions36 2022-11-04 23:42:28 -04:00
rocky
f59d0bf306 Misc lint 2022-11-04 03:54:01 -04:00
rocky
4959c76694 More 3.0 list comprehension bug fixes 2022-11-04 02:05:34 -04:00
rocky
766618ba48 Alow 3.0 setup 2022-11-04 00:53:45 -04:00
rocky
0be3fc657b Sync with 3.3-3.5 branch 2022-11-04 00:49:24 -04:00
rocky
d0a98bdbc6 Correct 3.0 list comprehension parsing 2022-11-04 00:42:50 -04:00
rocky
9ecdf12667 Some small typos and lint 2022-11-03 12:27:55 -04:00
rocky
f9aa2410d1 More float -> tuple version corrections 2022-11-03 12:20:10 -04:00
rocky
d6dcaff240 Fixes #414 2022-11-03 12:02:34 -04:00
rocky
5b3ea47bac Correct long-literals for Python 2.7 2022-10-16 19:33:51 -04:00
rocky
bb9b9fb4b3 Improve "if/else" in "for" test 2022-10-16 18:24:48 -04:00
rocky
1819fc8944 ifelsetmt - jump back is only allowed inside loops 2022-10-16 17:50:58 -04:00
R. Bernstein
8e6a0b01fa Merge pull request #413 from Berbe/for-loop
Fix: CONTINUE in else block in a for loop
2022-10-16 17:46:26 -04:00
Berbe
512c500810 Add: Tests: CONTINUE in else block in a for loop 2022-10-10 20:33:19 +02:00
rocky
976705fc0a Add: Python 2.7: ifelsestmtc 2022-10-10 04:30:48 +02:00
rocky
ae46ccf6d3 Go over 2.7 stdlib exclusions 2022-09-30 20:09:41 -04:00
rocky
a1cc0aab37 Move test: all() not in 2.4 2022-09-30 03:45:24 -04:00
rocky
0c7427069e strings need quotes in ADD_VALUE instructions 2022-09-30 03:33:47 -04:00
rocky
2264ccb1d5 A partial reduce-action sync with decompyle3
Start us add _check prefixes and _invalid to the end of check methods
2022-09-30 02:45:52 -04:00
rocky
3bd3029169 Confused == with = 2022-09-29 20:08:07 -04:00
rocky
ad1fa98870 Detect Python 2.7 weird "for-block" bytecode
It has an unnecessary JUMP_ABSOLUTE to a JUMP_LOOP

Fixes #408
2022-09-27 08:58:35 -04:00
rocky
8c85260852 Lint-like changes from VSCode
Also allow 3.11 to run this
2022-09-21 08:29:06 -04:00
rocky
62b816c60b Correct a signature return 2022-09-21 02:08:08 -04:00
rocky
d0f173a620 Lint from pycharm 2022-09-21 01:53:56 -04:00
rocky
7c3aff19af "async for"s can has pass blocks 2022-09-21 00:27:40 -04:00
rocky
be9af85e16 Hande Python 3.5 make_function() semantic action
Fixes #409
2022-09-21 00:19:37 -04:00
rocky
6c116fe4f9 Bump default master Python version 2022-09-20 17:35:33 -04:00
rocky
62760eb556 Deal with 2.x EXTENDED_ARGS on JUMP_ABSOLUTE
in scanner2's "continue" detection

Fixes #310
2022-09-18 21:12:27 -04:00
rocky
600688a65d Sync with decompyle3 2022-09-17 10:54:09 -04:00
rocky
a68f440d6f Sync with decompyle3
Better PyPy 3.7 tolerance
2022-09-17 01:59:42 -04:00
rocky
f913306070 Use github xdis...
So we pick up newer versions of Python 3.{7,8,9}.14 & 3.10.7
2022-09-16 19:03:00 -04:00
rocky
04df8a98fb uncompyle6.disasm -> uncompyle6.code_fns 2022-09-16 15:46:46 -04:00
rocky
4b2a2e218a Misc lint stuff from pycharm...
that has been applied to decompyle3 already
2022-09-16 15:38:13 -04:00
rocky
4260deea11 Tidy ifelsemstmt check 2022-08-29 05:46:46 -04:00
R. Bernstein
200250df56 Merge pull request #406 from tangboxuan/master
Fix offset of extended argument instruction
2022-08-24 05:51:41 -04:00
rocky
765b0149ea iftstmt reduce rule for 2.6:
In ifsmt there can be a JUMP_ABSOLUTE right before the endif and a jump
the endif doesn't fall through to the place after the endif.
2022-08-24 05:33:22 -04:00
Bo Xuan
2f3b5e53d4 Add test case 2022-08-24 16:19:39 +08:00
rocky
3cc51aa37f Reduce 2.6 excluded tests 2022-08-23 21:51:33 -04:00
R. Bernstein
19152e7ed8 Merge pull request #407 from rocky/python-2.6-if-fixup
Push reducechecks from 2.7 into 2.6
2022-08-23 21:41:16 -04:00
rocky
71b1446c9c Push reducechecks from 2.7 into 2.6
Some adaption is needed. These rules may also help earlier 2.x Python as well
2022-08-23 21:36:55 -04:00
rocky
14aa0ce8f0 sort a list 2022-08-23 20:17:06 -04:00
rocky
dfd8762dbd Update 2.6 exclude list 2022-08-23 17:26:45 -04:00
rocky
21b4d52a77 Correct 2.6 erroneous ifelse detection 2022-08-23 16:50:50 -04:00
rocky
9da3e4b3c0 For some 2.6 test PYTHON needs to be set to pytest 2022-08-23 08:11:06 -04:00
rocky
d73d0dd11a PYTHON_VERSION -> PYTHON_VERSION_TRIPLE 2022-08-23 06:54:23 -04:00
Bo Xuan
81633b3c1c Fix offset of extended argument instruction 2022-08-23 14:18:31 +08:00
rocky
4120213710 Update link which has gone stale 2022-08-14 20:32:47 -04:00
rocky
610f2c827c Remove 3.6-specific iflastsmt reduce check
Fixes #344
2022-07-07 06:54:05 -04:00
rocky
5a4136a7f6 Some limited support for 3.8 "=" specifier 2022-07-06 13:00:52 -04:00
rocky
cc4ea47d24 Use ifelsetmt reduction rule on 2.7 2022-07-04 07:56:44 -04:00
rocky
85ba8352ba Port over some recent decompyle3 3.8 fixes 2022-06-26 04:26:15 -04:00
rocky
7f798541f0 Python 3.8 while and whileTrue loops 2022-06-16 15:42:51 -04:00
rocky
7fb483c566 Sync up with decompile3's 3.8 try/else handling 2022-06-08 12:49:23 -04:00
rocky
6597737709 Merge branch 'master' of github.com:rocky/python-uncompyle6 2022-05-28 15:48:28 -04:00
rocky
c08ab41afd Go over what constitutes a bug, yet again 2022-05-28 15:45:51 -04:00
rocky
2cc58fec97 Note narrowing bug 2022-05-21 12:30:21 -04:00
rocky
8f7f0be7fa Administrivia
Workflows CI: go back to released versions rather than github versions
pyenv-newest-versions: updaed to use newest Python releases
pypy38.py: fix wrong package name import
3.6-exclude.sh: update and advance
2022-05-20 06:44:20 -04:00
rocky
3f4e85695e Reduce 3.7 exclusion tests 2022-05-14 22:24:25 -04:00
rocky
5c29b9a5e5 remove \n in lambda; 2.6 grammar cleanup 2022-05-14 20:28:24 -04:00
rocky
fa9cc4c669 Correct 2.5-7 relative import formatting 2022-05-14 19:35:24 -04:00
rocky
656a9aa290 Bugs in 2.x relative import '.' and 1.x bytecode 2022-05-14 17:46:48 -04:00
rocky
021810bb2c Correct 2.x formatting "slice2" nonterminal 2022-05-14 16:54:50 -04:00
rocky
223804ac1f semi-black scanner26.py 2022-05-14 09:51:50 -04:00
rocky
3a9fa652b4 Partial sync of 3.7 & 3.8 scanner with decompyle3 2022-05-14 08:42:04 -04:00
rocky
87fb83de08 Add missing 3.7 "import_from37" template 2022-05-14 02:59:15 -04:00
R. Bernstein
fbe4be3bb0 Merge pull request #399 from rocky/genexpr-3.6
3.6 async hacking
2022-05-07 07:10:33 -04:00
rocky
9b80663529 3.6 async hacking 2022-05-07 07:01:39 -04:00
rocky
dae00e9b0b More 3.6 "async for" 2022-05-06 15:15:05 -04:00
R. Bernstein
3cbe7ba5d7 Merge pull request #398 from rocky/LOAD_ARG_for36
Use LOAD_ARG in 3.6
2022-05-06 13:45:52 -04:00
rocky
cca015c5d6 Use LOAD_ARG in 3.6 2022-05-06 12:53:55 -04:00
rocky
cc47d61efa Better 3.6 set comprehensions 2022-05-06 07:30:56 -04:00
R. Bernstein
b421b00b53 Merge pull request #397 from rocky/LOAD_ARG
Classify LOAD_ARG as LOAD_FAST of .0
2022-05-06 03:06:19 -04:00
rocky
92b8d9c508 Grammar lint adjustments 2022-05-06 03:02:30 -04:00
rocky
f5043408ec Start rolling in LOAD_ARG for 3.7+ 2022-05-06 02:41:02 -04:00
rocky
8576117d00 Fix More 3.6 async parsing
... all from 3.6 test_coroutines.py.

More bugs remain
2022-05-05 07:36:06 -04:00
rocky
c5efec1e6f Fox some 3.6 async_forelse parsing 2022-05-05 07:09:39 -04:00
rocky
f9a1f6fcd9 Sync 3.7 async_forelse with decompyle3 2022-05-05 06:47:49 -04:00
rocky
c9f33edde4 Handle 3.6 "async for" better 2022-05-04 19:21:07 -04:00
rocky
9dd4a53ff8 Fix 3.6 async parsing 2022-05-04 04:27:38 -04:00
rocky
d62310f799 Correct 3.6ish dictionary literals printing 2022-05-03 12:19:43 -04:00
rocky
ac862b4566 In Python 2.2- preserve line numbers 2022-05-03 07:15:18 -04:00
rocky
e94e9379c0 Bang on version 1.0-1.4 Python 2022-05-02 22:03:52 -04:00
rocky
5df57489b4 CI woes - need new xdis
Remove 1.0 os.pyc until I can investigate.
It works locally though
2022-04-30 20:50:28 -04:00
rocky
9aba1cc3af Bytecode 1.x fixes 2022-04-30 20:36:43 -04:00
rocky
eba0d37d0f Improve Python 1.x decompiling
Still has bugs, but is much better.
2022-04-30 05:54:22 -04:00
rocky
5e1ba2baa1 Split long lines in n_const_list 2022-04-28 18:03:15 -04:00
rocky
f35231a6f5 Correct bug in long literal replacement for 2.6-7 2022-04-28 17:28:09 -04:00
rocky
37ea469ce6 One more 2.4 test 2022-04-28 17:11:17 -04:00
rocky
8e5faa933f Handle long 2.x bytecode literals more efficiently 2022-04-27 13:47:56 -04:00
rocky
cfd6166d8d Small doc corrections 2022-04-27 05:07:07 -04:00
rocky
a356a8e0ee Reinstante pyenvlib 2022-04-27 03:39:05 -04:00
rocky
152de50f90 Revise docstring explaiing pydisassemble 2022-04-26 18:12:26 -04:00
rocky
1c49eb5989 Revise what pydisassemble is about 2022-04-26 18:09:16 -04:00
rocky
c25fa61e33 Start handling BUILD_MAP (a class of dict) 2022-04-26 15:37:42 -04:00
R. Bernstein
81ff994a41 Merge pull request #394 from rocky/long-collection-python3
Long collection python3
2022-04-26 03:18:16 -04:00
rocky
d48801964c Use attr insead of pattrr for non-strings 2022-04-26 03:13:27 -04:00
rocky
4879a60ecc Some bugs creating token stream ..
from instructions.
2022-04-25 17:39:39 -04:00
rocky
bf58fb9cf2 WIP - extend fast long-literals into older Python3 2022-04-25 08:06:46 -04:00
rocky
c6642f5899 Revise "ingest" docstring 2022-04-25 07:42:56 -04:00
R. Bernstein
13266d1b56 Merge pull request #393 from rocky/speedup-long-collections
Speedup long collections
2022-04-24 18:00:11 -04:00
rocky
e564ac3ab1 Go over long-literal test 2022-04-24 17:50:32 -04:00
rocky
8cdf741b62 Bugs in long-literal handlin
Move n_dict to n_actions and special case n_const_list.
Generalize build_collection out of 3.7+ and into all Pythons
2022-04-24 17:38:35 -04:00
rocky
371138cfbc handle long literal constants faster 2022-04-24 13:11:20 -04:00
rocky
464801bcb3 Correct type annotation on decompile()
Fixes #391
2022-04-21 20:10:33 -04:00
rocky
f3ac70d0ea test tweak again 2022-04-21 05:34:15 -04:00
rocky
433d7003e0 Add "transfrormd_by" param to SyntaxTree
This aligns code more with decompyle3
2022-04-21 05:25:14 -04:00
rocky
c88d9de316 Correct 3.7 "impor"t and "from .. import" 2022-04-20 20:03:28 -04:00
rocky
e2ff909603 Split off (semantic) nonterminal print actions 2022-04-19 16:42:48 -04:00
rocky
3662f3e8c6 Fold in some decompile changes 2022-04-17 12:20:03 -04:00
rocky
c806ef59c6 Update scanner demo code 2022-04-17 11:41:19 -04:00
rocky
f8ae674890 Split out comprehension code..
sync with decompile a little better
2022-04-17 10:52:56 -04:00
rocky
1c1752d6d6 Bump testing version ...
pyston 2.3 testing
2022-04-17 10:29:23 -04:00
rocky
420d22c094 Correct for pypy 3.7 2022-04-15 08:36:42 -04:00
rocky
faac21d1e4 Bump testing versions 2022-04-15 08:25:38 -04:00
rocky
a26ac79d0f Sync up decompyle3 customize37 somewhat 2022-04-15 08:22:45 -04:00
rocky
1a673aba40 Reinstate a test 2022-04-13 03:05:04 -04:00
rocky
04510ac2f8 lambda formatting in f-string
In a formatted string using "lambda',  we should not add "\n".
For example in:
  f'{(lambda x:x)("8")!r}'

Adding a "\n" after "lambda x: x" will give an error message:
  SyntaxError: f-string expression part cannot include a backslash
2022-04-12 16:49:58 -04:00
rocky
a1fe069c8c Handle walrus operator
Or rather set precedence on call_stmt and expr_stmt

Adjust pytest test_single_compile so it works now
2022-04-12 05:21:13 -04:00
rocky
e7fd592313 Update bug template 2022-04-11 13:06:39 -04:00
rocky
728954295f Note that you can pay me for personal help 2022-04-10 13:02:58 -04:00
rocky
83ab85353b Remove a reference to an unset local variable
See also https://github.com/rocky/python-uncompyle6/pull/388
2022-04-09 02:29:44 -04:00
rocky
bc71bf7acd Shorten 10_complex.py
Runtime testing took too long because ranges were larger than needed
Also use newer convention for marking runable codes
2022-04-03 06:41:58 -04:00
rocky
9735453283 Small changes
test code for pysource and bump lastest testing Python versions
2022-04-01 03:11:59 -04:00
rocky
7f9014fb05 Add Table of Contents 2022-03-12 05:26:01 -05:00
rocky
e14b8dd496 Sync with decompyle3 2022-03-12 05:18:24 -05:00
rocky
aaa737672b Mention pydeinstaller 2022-03-12 04:56:33 -05:00
R. Bernstein
2198f9bbaa Update HOW-TO-REPORT-A-BUG.md 2022-03-12 04:52:11 -05:00
R. Bernstein
b7015b16b0 Update HOW-TO-REPORT-A-BUG.md 2022-03-12 04:49:33 -05:00
R. Bernstein
67bb8223d8 Update HOW-TO-REPORT-A-BUG.md 2022-03-12 04:48:07 -05:00
R. Bernstein
2faa7b0597 Update HOW-TO-REPORT-A-BUG.md 2022-03-12 04:43:08 -05:00
R. Bernstein
58f00b1e5b Update HOW-TO-REPORT-A-BUG.md 2022-03-12 04:39:39 -05:00
rocky
3d24de7ce5 __init__.py lint 2022-03-09 12:16:38 -05:00
R. Bernstein
b270f6eed7 Update HOW-TO-REPORT-A-BUG.md 2022-03-05 05:27:21 -05:00
R. Bernstein
e81d944c12 Update HOW-TO-REPORT-A-BUG.md 2022-03-05 05:26:26 -05:00
rocky
2718492001 spell check 2022-03-05 05:08:52 -05:00
R. Bernstein
68d6bc2fa1 Update HOW-TO-REPORT-A-BUG.md 2022-03-05 04:58:33 -05:00
rocky
884c15e84a Update toc 2022-03-05 04:57:55 -05:00
rocky
82456c15e1 Reduce check type for 2.5 and update bug reporting 2022-03-05 04:55:11 -05:00
rocky
09c10f51fa Revise README 2022-03-05 04:20:30 -05:00
rocky
3490389a66 Correct some Python 2.6 chain compare bugs 2022-03-05 04:03:27 -05:00
rocky
d366248b47 Some small variable-name changes 2022-03-04 04:47:38 -05:00
rocky
6f112ec5b2 Ensure no parens on subscript slice 2022-03-03 21:05:47 -05:00
rocky
219cb0606a MAKE_FUNCTION_8 -> MAKE_FUNCTION_CLOSURE
Clarity is important.
2022-02-27 10:29:53 -05:00
rocky
ce5207333f Remove TABLE_R0 - it hasn't been used in a while 2022-02-27 10:18:57 -05:00
rocky
f2a70a2758 Sync with decompyle3 for async "for"
More work is needed though
2022-01-18 15:25:51 -05:00
rocky
5b5fa310d9 Partial 3.8 async "for" fixes 2022-01-18 13:08:17 -05:00
rocky
88c0c03ee4 setcomprehension_walk3 -> closure_walk 2022-01-14 07:50:39 -05:00
rocky
a381b4663b Adapt for recent options changes in
-T option structure changed.
2022-01-09 16:01:32 -05:00
R. Bernstein
2fda52bf45 Merge pull request #382 from lostbeta/master
Fix version check comparison
2022-01-09 14:48:42 -05:00
lostBeta
415cba6978 Fix version check comparison 2022-01-09 18:52:48 +02:00
rocky
15761acd0d Revise options processing. Sync with decompyle3
We should now handle passing assembly options or functions and
subroutines more properly.

The "%P" and "%p" specifiers now allow lists of nonterminals like "%c"
and "%C" do.

version was bumped because top-level main parameter args change slightly.
2022-01-09 04:11:09 -05:00
R. Bernstein
1c0fc283b1 Merge pull request #381 from rocky/return-expr
ret_expr -> return_expr
2022-01-03 22:02:43 -05:00
rocky
deea74b6a8 ret_expr -> return_expr
This matches Python's AST a little more closely
2022-01-03 21:56:07 -05:00
R. Bernstein
7f42694c25 Merge pull request #380 from rocky/return_expr_lambda
return_lambda -> return_expr_lambda
2022-01-01 22:41:12 -05:00
rocky
3d5b6f4654 return_lambda -> return_expr_lambda
Except those places in 2.6ish code where it is simple a fancy RETURN_VALUE
2022-01-01 21:45:51 -05:00
rocky
51e32b88a4 Include 2.4_run, 2.5_run in testing 2021-12-31 11:39:57 -05:00
R. Bernstein
b7583dfb60 Merge pull request #379 from rocky/elif-transformation-with-continue
Elif transformation with continue
2021-12-31 11:32:23 -05:00
rocky
203139eafa Add tests, comment what's up with change..
and use isinstance()
2021-12-31 11:27:15 -05:00
R. Bernstein
9172f82bae Merge pull request #378 from dkw72n/wrong_type
Fix #377
2021-12-31 11:07:14 -05:00
dkw72n
d9de4ea245 Fix #377 2021-12-31 16:11:27 +08:00
rocky
3b96313fd8 Revise README.rst 2021-12-28 23:16:53 -05:00
R. Bernstein
2070208ca3 Update NEW_FEATURES.rst 2021-12-27 19:13:00 -05:00
rocky
88e169adca More verbiage on what we have and what's happened. 2021-12-27 16:28:28 -05:00
rocky
165115289a dict_unmap -> dict_unpack matches Python AST better 2021-12-26 19:03:58 -05:00
rocky
3234673422 mklambda -> lambda_body matches Python AST better
Note: we can't use "lambda" since that is a reserved word
2021-12-26 18:48:51 -05:00
rocky
23551ea70f unmap_dict -> dict_doublestar ...
This matches Python's AST (Dict) better. Variations or specializations
of an AST name, e.g. "unmap" should come at the end, not the beginning.
2021-12-23 22:57:15 -05:00
rocky
30aad42aae Sync with other versions 2021-12-23 16:46:25 -05:00
rocky
a3bc9bb32b Add operator precedence to -T output 2021-12-23 16:11:25 -05:00
rocky
8deb940b21 Update and revise HISTORY
Remove some of the older history and put a link to that which is nos
recorded in decompyle-2.4's history.
2021-12-22 21:49:38 -05:00
rocky
b3aaff0201 Sync pysource with decompyle3 2021-12-18 03:03:50 -05:00
rocky
da2314f5ae Part of the decompye3 loop "continue" fixes 2021-12-17 16:13:09 -05:00
rocky
16c900ff1d Propagate show_asm debug option down to functions 2021-12-17 06:07:18 -05:00
rocky
ed5346e526 Another pass clarifying what's okay as bug report 2021-11-30 03:33:20 -05:00
rocky
e718b794f3 Administrivia 2021-11-28 06:20:25 -05:00
rocky
03a71290e9 Admnistrivia
revise add-test.py
2021-11-24 15:12:53 -05:00
rocky
2c4acecc9d Start PyPy 3.8 support 2021-11-23 16:45:01 -05:00
rocky
2d5249f1d3 Small comment change 2021-11-23 07:31:37 -05:00
rocky
223b9e1d88 Extent METHOD_CALL_KW to PyPy 3.8 2021-11-23 07:23:23 -05:00
rocky
211c74c240 Better 3.7 CALL_METHOD_KW handling
- Handles positional args now
2021-11-23 05:06:48 -05:00
rocky
3a63847d22 Tweak last commit 2021-11-22 09:27:16 -05:00
rocky
2ed211e0d4 Some PyPY 3.7 support
* Handle CALL_METHOD_KW
* adjust PyPY 3.7 assert stmts
* misc administrivia
2021-11-21 14:04:34 -05:00
rocky
d752f63d12 PyPy 3.7 scanner bug 2021-11-21 00:06:45 -05:00
rocky
88dd5d7756 Remove one more float version test 2021-11-16 06:47:31 -05:00
rocky
4d351e31cd Administrivia: workflows CI 2021-11-07 10:23:12 -05:00
rocky
69387c4173 Tidy scanner more 2021-11-03 05:03:53 -04:00
rocky
22baad273f Sync with decompyle start using types more. 2021-11-03 04:58:41 -04:00
rocky
8094f3bb12 Remove PYTHON3 2021-11-03 03:00:43 -04:00
rocky
f6f0e344d0 Python 3.6+ specialization 2021-11-03 02:23:19 -04:00
rocky
6af63deaa3 Merge branch 'master' of github.com:rocky/python-uncompyle6 2021-11-03 01:26:06 -04:00
R. Bernstein
9b5d953614 Merge pull request #364 from rocky/PYTHON3-move
use xdis.PYTHON3 not uncompyle.PYTHON3
2021-11-03 01:24:47 -04:00
R. Bernstein
33c61137d8 Merge pull request #364 from rocky/PYTHON3-move
use xdis.PYTHON3 not uncompyle.PYTHON3
2021-11-02 06:57:29 -04:00
rocky
ed34bf9d4a use xdis.PYTHON3 not uncompyle.PYTHON3 2021-11-02 06:53:11 -04:00
R. Bernstein
b4912e7b64 Merge pull request #365 from elfring/Increase_the_usage_of_augmented_assignment_statements
Convert 14 statements to the usage of augmented assignments
2021-11-02 06:51:02 -04:00
Markus Elfring
05761b0d46 Issue #363: Convert 14 statements to the usage of augmented assignments
Augmented assignment statements became available with Python 2.
https://docs.python.org/3/whatsnew/2.0.html#augmented-assignment

Thus adjust 14 source code places accordingly.

Signed-off-by: Markus Elfring <elfring@users.sourceforge.net>
2021-11-02 11:25:04 +01:00
rocky
7fd1cea877 Start PyPY 3.7 and 3.8 decompilation support 2021-11-02 06:05:09 -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
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
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
ea26084e6d Modernize and sync with decompyle3 better 2021-10-25 09:13:47 -04:00
rocky
fa203af665 Better messages when xdis not handling Python x.y 2021-10-24 23:22:41 -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
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
71fe1e6c2c Fragment and other bugs
Part of the upgrade process
2021-10-23 09:47:30 -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
e3369edaed DRY using version_info_to_str 2021-10-23 08:24:35 -04:00
rocky
0a9dc57cc9 Try 3.6 CI testing 2021-10-21 18:53:44 -04:00
rocky
48bd832e7c Adminsitrivia 2021-10-21 16:36:46 -04:00
rocky
29a91fc015 Version twiddling 2021-10-21 16:33:09 -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
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
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
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
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
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
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
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
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
430fd2fa85 Update README.rst status on early Pythons 2020-07-06 12:02:59 -04:00
rocky
ef59b9c304 Forelse reduction checks on 2.6 2020-07-06 10:09:42 -04:00
rocky
084e183577 Add reduce check for 2.7 except_handler range 2020-07-05 22:18:07 -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
b21e8b8b57 Get ready for release 3.7.2 2020-06-27 23:08:46 -04:00
rocky
4007b8b702 Back off "or" check using instructions vs opcodes 2020-06-27 11:44:23 -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
357f28dd89 Add "comp_if_not" for 2.6- 2020-06-27 11:16:47 -04:00
rocky
5cc572147a Handle more ifelse reduction rules patterns 2020-06-27 09:10:48 -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
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
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
rocky
02f502c40a New grammar rule often imples expanded reduce rule 2020-06-12 21:12:02 -04:00
rocky
de4fbb08f2 Get ready for release 3.7.1 2020-06-12 20:20:58 -04:00
rocky
e14675c2dc Handle 3.7+ "else" branch removal...
As seen in _cmp() of python3.8/distutils/version.py with optimization -O2
2020-06-12 13:18:33 -04:00
rocky
3449be024b CI take 3. 2020-06-10 22:18:28 -04:00
rocky
8b50b15f0a CI update take 2 2020-06-10 22:17:13 -04:00
rocky
e2e925679d Update CI to use git xdis 2020-06-10 22:15:55 -04:00
rocky
7deeee8502 Push "with" grammar improvements back to 3.6 2020-06-04 05:53:21 -04:00
rocky
acdd025162 ast-check "for" is a loop; sync "withas" test ..
with decompyle3.
2020-06-04 05:34:19 -04:00
rocky
9acb3cf068 Fix bug in 3.8 with .. as 2020-06-04 05:24:22 -04:00
rocky
40a653cd3b Bump min xdis version...
it fixes a bug in stdlib testing
2020-05-31 03:17:09 -04:00
rocky
3ac3979535 With a newer xdis, some stdlib test work now 2020-05-31 03:10:52 -04:00
rocky
7eba933cfa More excludes 2020-05-24 21:25:07 -04:00
rocky
ad5d3333da A regression regarding "and"/"or" with "continue" 2020-05-19 10:20:08 -04:00
rocky
e046323b31 Some typos 2020-05-19 01:35:50 -04:00
rocky
e80c13170a Administrivia 2020-05-19 01:29:09 -04:00
rocky
889417caeb Get ready for release 3.7.0 2020-05-19 01:17:58 -04:00
rocky
5a83c7c643 Simplify imports again using xdis 4.6.0 2020-05-19 00:53:53 -04:00
rocky
31db2f3e04 Small typo 2020-05-18 23:29:33 -04:00
rocky
7fa851765d Regularize "or" so args are in 1..2 and ...
correct "return None" semantic action
2020-05-18 22:55:26 -04:00
rocky
d7c3b8454b 3.8 needs call_stmt -> call
Simplify/regularize how "return" works
2020-05-18 22:26:18 -04:00
rocky
3fb8d90407 Revise for xdis 3.6.0 ...
Simplify xdis imports where we can.
Blacken (most) of those buffers too
2020-05-18 21:49:16 -04:00
rocky
ff43565981 3.4-3.4 mixed "and"/"or" parsing ...
Fix by limiting more the bogus come from.
2020-05-18 05:33:57 -04:00
rocky
4365022f40 Adapt decompyle3's 3.8 try/return grammar rules 2020-05-17 10:18:10 -04:00
rocky
d343384db7 A runnable "async" and "async with" test 2020-05-16 07:55:51 -04:00
rocky
87a891ca54 Skip 2.6 test until I can get around to it. 2020-05-14 23:50:55 -04:00
rocky
b94c649776 3.7 change rule to match op "or" expr's 2020-05-14 21:32:45 -04:00
R. Bernstein
f34375ba99 Create FUNDING.yml 2020-05-14 12:12:18 -04:00
rocky
81b704f597 Simpify an import, blacken a file. 2020-05-09 09:32:44 -04:00
rocky
5233a0716b Correct wong class names in super() 2020-05-08 05:59:20 -04:00
rocky
a810ed1280 Merge branch 'master' of github.com:rocky/python-uncompyle6 2020-05-05 22:18:22 -04:00
rocky
ab54caae34 Runtest.sh improvements 2020-05-05 22:18:15 -04:00
rocky
d3cf87e2d9 Start marking test suite since this is going to be copied 2020-05-04 11:43:16 -04:00
rocky
c5228dbdc4 Small test doc typo 2020-05-01 23:19:31 -04:00
rocky
a72163f6f9 lint 2020-04-30 18:00:04 -04:00
rocky
3e1300eb23 Bugs in nested async for...
* Generalize asyc_for rule
 Fix bug in picking out comprehension iterator in async for
* fix bug in getting expression in such a comprehension
* Add %[n]{%x} pattern to template_engine()
2020-04-29 10:12:54 -04:00
rocky
a4eaeea5b2 See above. 2020-04-27 23:05:05 -04:00
rocky
1141dfefc2 Typo in appveyor config 2020-04-27 23:03:46 -04:00
354 changed files with 16131 additions and 7076 deletions

View File

@@ -1,4 +1,7 @@
version: 2
filters:
branches:
only: master
jobs:
build:
working_directory: ~/rocky/python-uncompyle6
@@ -13,58 +16,65 @@ jobs:
# To see the list of pre-built images that CircleCI provides for most common languages see
# https://circleci.com/docs/2.0/circleci-images/
docker:
- image: circleci/python:3.6.9
- image: circleci/python:3.8
steps:
# Machine Setup
# If you break your build into multiple jobs with workflows, you will probably want to do the parts of this that are relevant in each
# The following `checkout` command checks out your code to your working directory. In 1.0 we did this implicitly. In 2.0 you can choose where in the course of a job your code should be checked out.
- checkout
# Prepare for artifact and test results collection equivalent to how it was done on 1.0.
# In many cases you can simplify this from what is generated here.
# 'See docs on artifact collection here https://circleci.com/docs/2.0/artifacts/'
- run: mkdir -p $CIRCLE_ARTIFACTS $CIRCLE_TEST_REPORTS
# This is based on your 1.0 configuration file or project settings
- run:
working_directory: ~/rocky/python-uncompyle6
command: pip install --user virtualenv && pip install --user nose && pip install --user pep8
# Dependencies
# This would typically go in either a build or a build-and-test job when using workflows
# Restore the dependency cache
- restore_cache:
keys:
- v2-dependencies-{{ .Branch }}-
# fallback to using the latest cache if no exact match is found
- v2-dependencies-
# Machine Setup
# If you break your build into multiple jobs with workflows, you will probably want to do the parts of this that are relevant in each
# The following `checkout` command checks out your code to your working directory. In 1.0 we did this implicitly. In 2.0 you can choose where in the course of a job your code should be checked out.
- checkout
# Prepare for artifact and test results collection equivalent to how it was done on 1.0.
# In many cases you can simplify this from what is generated here.
# 'See docs on artifact collection here https://circleci.com/docs/2.0/artifacts/'
- run: mkdir -p $CIRCLE_ARTIFACTS $CIRCLE_TEST_REPORTS
# This is based on your 1.0 configuration file or project settings
- run:
working_directory: ~/rocky/python-uncompyle6
command: pip install --user virtualenv && pip install --user nose && pip install
--user pep8
# Dependencies
# This would typically go in either a build or a build-and-test job when using workflows
# Restore the dependency cache
- restore_cache:
keys:
- v2-dependencies-{{ .Branch }}-
# fallback to using the latest cache if no exact match is found
- v2-dependencies-
- run: pip install --user --upgrade setuptools
- run: pip install --user -e .
- run: pip install --user -r requirements-dev.txt
- run:
command: | # Use pip to install dependengcies
sudo pip install --user --upgrade setuptools
pip install --user -e .
# Not sure why "pip install -e" doesn't work above
# pip install click spark-parser xdis
pip install --user -r requirements-dev.txt
# Save dependency cache
- save_cache:
key: v2-dependencies-{{ .Branch }}-{{ epoch }}
paths:
# This is a broad list of cache paths to include many possible development environments
# You can probably delete some of these entries
- vendor/bundle
- ~/virtualenvs
- ~/.m2
- ~/.ivy2
- ~/.bundle
- ~/.cache/bower
# Save dependency cache
- save_cache:
key: v2-dependencies-{{ .Branch }}-{{ epoch }}
paths:
# This is a broad list of cache paths to include many possible development environments
# You can probably delete some of these entries
- vendor/bundle
- ~/virtualenvs
- ~/.m2
- ~/.ivy2
- ~/.bundle
- ~/.cache/bower
# Test
# This would typically be a build job when using workflows, possibly combined with build
# This is based on your 1.0 configuration file or project settings
- run: sudo python ./setup.py develop && make check-3.6
- run: cd ./test/stdlib && bash ./runtests.sh 'test_[p-z]*.py'
# Teardown
# If you break your build into multiple jobs with workflows, you will probably want to do the parts of this that are relevant in each
# Save test results
- store_test_results:
path: /tmp/circleci-test-results
# Save artifacts
- store_artifacts:
path: /tmp/circleci-artifacts
- store_artifacts:
path: /tmp/circleci-test-results
# Test
# This would typically be a build job when using workflows, possibly combined with build
# This is based on your 1.0 configuration file or project settings
- run: sudo pip install -e . && make check-3.6
- run: cd ./test/stdlib && bash ./runtests.sh 'test_[p-z]*.py'
# Teardown
# If you break your build into multiple jobs with workflows, you will probably want to do the parts of this that are relevant in each
# Save test results
- store_test_results:
path: /tmp/circleci-test-results
# Save artifacts
- store_artifacts:
path: /tmp/circleci-artifacts
- store_artifacts:
path: /tmp/circleci-test-results
# The resource_class feature allows configuring CPU and RAM resources for each job. Different resource classes are available for different executors. https://circleci.com/docs/2.0/configuration-reference/#resourceclass
resource_class: large

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

12
.github/FUNDING.yml vendored Normal file
View File

@@ -0,0 +1,12 @@
# These are supported funding model platforms
github: [rocky]
patreon: # Replace with a single Patreon username
open_collective: # Replace with a single Open Collective username
ko_fi: # Replace with a single Ko-fi username
tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel
community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry
liberapay: rocky
issuehunt: # Replace with a single IssueHunt username
otechie: # Replace with a single Otechie username
custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2']

View File

@@ -4,34 +4,74 @@ 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:__ If you are using this program to do something illegal - don't.
The issue may be flagged to make it easier for those looking for illegal activity.
If you are reporting a bug in decompilation, it will probably not be acted upon
unless it is narrowed to a small example. You may have to do some work remove
extraneous code from the source example. Most bugs can be expressed in 30 lines of
code.
Issues 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 tolerant of this if you sponsor the project.
Bugs are also not for general or novice kind help on how to install
this Python program and its dependencies in your environment, or in
the way you would like to have it set up, or how to interpret a Python
traceback e.g. that winds up saying Python X.Y.Z is not supported.
For these kinds of things, you will save yourself time by asking
instead on forums like StackOverflow that are geared to helping people
for such general or novice kinds questions and tasks. And unless you
are a sponsor of the project, if your question seems to be of this
category, the issue may just be closed.
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 partially 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.
Tasks or the kinds of things others can do, but you can't do or don't
want to do yourself are typically the kind of thing that you pay
someone to do, especially when you are the primary beneficiary of the
work, or the task is complex, long, or tedious. If your code is over
30 lines long, it fits into this category.
See also https://github.com/rocky/python-uncomp[yle6/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.
* Try to make the bytecode that exhibits a bug as small as possible.
* 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,
requires registration to download. Instead attach it as a zip file.
* 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 suspicious, 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.
-->
## Description
<!-- Add a clear and concise description of the bug. -->
<!-- Please add a clear and concise description of the bug. Try to narrow the problem down to the smallest that exhibits the bug.-->
## How to Reproduce
@@ -46,12 +86,22 @@ $ uncompyle6 <command-line-options>
$
```
Provide links to the Python bytecode. For example you can create a
Attach a zip file to the Python bytecode or a
gist with the information. If you have the correct source code, you
can add that too.
-->
## Output Given
<!--
Please include not just the error message but all output leading to the message which includes echoing input and messages up to the error.
For a command-line environment include command invocation and all the output produced.
If this is too long, then try narrowing the problem to something short.
-->
## Expected behavior
<!-- Add a clear and concise description of what you expected to happen. -->
@@ -63,12 +113,25 @@ can add that too.
Please modify for your setup
- Uncompyle6 version: output from `uncompyle6 --version` or `pip show uncompyle6`
- Python version for the version of Python the byte-compiled the file: `python -c "import sys; print(sys.version)"` where `python` is the correct Cpython or Pypy binary.
- xdis version: output from `pydisasm --version` or or `pip show xdis`
- Python version for the version of Python the byte-compiled the file: `python -c "import sys; print(sys.version)"` where `python` is the correct CPython or PyPy binary.
- OS and Version: [e.g. Ubuntu bionic]
-->
## Additional Environment or Context
## Workarounds
<!-- If there is a workaround for the problem, describe that here. -->
## Priority
<!-- If this is important for a particular public good state that here.
If this is blocking some important activity let us know what activity it blocks.
Otherwise, we'll assume this has the lowest priority in addressing.
-->
## Additional Context
<!-- _This section is optional._

1
.github/ISSUE_TEMPLATE/config.yml vendored Normal file
View File

@@ -0,0 +1 @@
blank_issues_enabled: False

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

@@ -0,0 +1,31 @@
name: uncompyle6 (osx)
on:
push:
branches: [ master ]
pull_request:
branches: [ master ]
jobs:
build:
runs-on: macos-latest
strategy:
matrix:
os: [macOS]
python-version: [3.8]
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
pip install -e .
# Not sure why "pip install -e" doesn't work above
# pip install click spark-parser xdis
pip install -r requirements-dev.txt
- name: Test uncompyle6
run: |
make check

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

@@ -0,0 +1,29 @@
name: uncompyle6 (ubuntu)
on:
push:
branches: [ master ]
pull_request:
branches: [ master ]
jobs:
build:
runs-on: ubuntu-latest
strategy:
matrix:
python-version: [3.8]
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
pip install -e .
# pip install click spark-parser xdis
pip install -r requirements-dev.txt
- name: Test uncompyle6
run: |
make check

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

@@ -0,0 +1,31 @@
name: uncompyle6 (windows)
on:
push:
branches: [ master ]
pull_request:
branches: [ master ]
jobs:
build:
runs-on: macos-latest
strategy:
matrix:
os: [windows]
python-version: [3.8]
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
pip install -e .
# Not sure why "pip install -e" doesn't work above
# pip install click spark-parser xdis
pip install -r requirements-dev.txt
- name: Test uncompyle6
run: |
make check

3
.gitignore vendored
View File

@@ -2,6 +2,7 @@
*.pyo
*_dis
*~
.mypy_cache
/.cache
/.eggs
/.hypothesis
@@ -16,9 +17,11 @@
/dist
/how-to-make-a-release.txt
/nose-*.egg
/pycharm-venv
/tmp
/uncompyle6.egg-info
/unpyc
/venv
ChangeLog
__pycache__
build

11
.isort.cfg Normal file
View File

@@ -0,0 +1,11 @@
[settings]
multi_line_output = 3
include_trailing_comma = True
force_grid_wrap = 0
use_parentheses = True
line_length = 88
known_crunch = cr, zz9d, zz9lib, pycrunch, silhouette
sections = FUTURE,STDLIB,THIRDPARTY,FIRSTPARTY,CRUNCH,LOCALFOLDER
default_section = THIRDPARTY
combine_as_imports = 1
profile = black

22
.pre-commit-config.yaml Normal file
View File

@@ -0,0 +1,22 @@
default_language_version:
python: python
repos:
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v4.5.0
hooks:
- id: check-merge-conflict
- id: debug-statements
stages: [pre-commit]
- id: end-of-file-fixer
stages: [pre-commit]
- repo: https://github.com/pycqa/isort
rev: 5.13.2
hooks:
- id: isort
stages: [pre-commit]
- repo: https://github.com/psf/black
rev: 23.12.1
hooks:
- id: black
language_version: python3
stages: [pre-commit]

View File

@@ -13,6 +13,8 @@ matrix:
dist: xenial # required for Python >= 3.7 (travis-ci/travis-ci#9069)
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

@@ -1,213 +1,93 @@
This project has history of over 18 years spanning back to Python 1.5
# Introduction
There have been a number of people who have worked on this. I am awed
by the amount of work, number of people who have contributed to this,
and the cleverness in the code.
This project started around 1999 spanning back to Python 1.5
The below is an annotated history from talking to participants
involved and my reading of the code and sources cited.
In the interest of shortening what is written here, I am going to start where we left off where [decompyle 2.4's history](https://github.com/rocky/decompile-2.4/blob/master/HISTORY.md) ends.
In 1998, John Aycock first wrote a grammar parser in Python,
eventually called SPARK, that was usable inside a Python program. This
code was described in the
[7th International Python Conference](http://legacy.python.org/workshops/1998-11/proceedings/papers/aycock-little/aycock-little.html). That
paper doesn't talk about decompilation, nor did John have that in mind
at that time. It does mention that a full parser for Python (rather
than the simple languages in the paper) was being considered.
For the earlier history up to 2006 and the code up until Python 2.4, which I find interesting, look at that link.
[This](http://pages.cpsc.ucalgary.ca/~aycock/spark/content.html#contributors)
contains a of people acknowledged in developing SPARK. What's amazing
about this code is that it is reasonably fast and has survived up to
Python 3 with relatively little change. This work was done in
conjunction with his Ph.D Thesis. This was finished around 2001. In
working on his thesis, John realized SPARK could be used to deparse
Python bytecode. In the fall of 1999, he started writing the Python
program, "decompyle", to do this.
Sometime around 2014 was the dawn of ["uncompyle" and PyPI](https://pypi.python.org/pypi/uncompyle/1.1) &mdash; the era of
public version control. Dan Pascu's code although not public used [darcs](http://darcs.net/) for version control. I converted the darcs repository to git and put this at [decompyle-2.4](https://github.com/rocky/decompile-2.4).
To help with control structure deparsing the instruction sequence was
augmented with pseudo instruction COME_FROM. This code introduced
another clever idea: using table-driven semantics routines, using
format specifiers.
# uncompyle, unpyc
The last mention of a release of SPARK from John is around 2002. As
released, although the Earley Algorithm parser was in good shape, this
code was woefully lacking as serious Python deparser.
In contrast to _decompyle_ that went up to Python 2.4, _uncompyle_, at least in its final versions, runs only on Python 2.7. However it accepts bytecode back to Python 2.5. Thomas Grainger is the package owner of this, although Hartmut is still listed as the author.
In the fall of 2000, Hartmut Goebel
[took over maintaining the code](https://groups.google.com/forum/#!searchin/comp.lang.python/hartmut$20goebel/comp.lang.python/35s3mp4-nuY/UZALti6ujnQJ). The
first subsequent public release announcement that I can find is
["decompyle - A byte-code-decompiler version 2.2 beta 1"](https://mail.python.org/pipermail/python-announce-list/2002-February/001272.html).
The project exists not only on [github](https://github.com/gstarnberger/uncompyle) but also on
[bitbucket](https://bitbucket.org/gstarnberger/uncompyle) and later the defunct [google
code](https://code.google.com/archive/p/unpyc/) under the name _unpyc_. The git/svn history goes back to 2009. Somewhere in there the name was changed from "decompyle" to "unpyc" by Keknehv, and then to "uncompyle" by Guenther Starnberger.
From the CHANGES file found in
[the tarball for that release](http://old-releases.ubuntu.com/ubuntu/pool/universe/d/decompyle2.2/decompyle2.2_2.2beta1.orig.tar.gz),
it appears that Hartmut did most of the work to get this code to
accept the full Python language. He added precedence to the table
specifiers, support for multiple versions of Python, the
pretty-printing of docstrings, lists, and hashes. He also wrote test and verification routines of
deparsed bytecode, and used this in an extensive set of tests that he also wrote. He says he could verify against the
entire Python library. However I have subsequently found small and relatively obscure bugs in the decompilation code.
The name Thomas Grainger isn't found in (m)any of the commits in the several years of active development. First Keknehv worked on this up to Python 2.5 or so while accepting Python bytecode back to 2.0 or so. Then "hamled" made a few commits earlier on, while Eike Siewertsen made a few commits later on. But mostly "wibiti", and Guenther Starnberger got the code to where uncompyle2 was around 2012.
decompyle2.2 was packaged for Debian (sarge) by
[Ben Burton around 2002](https://packages.qa.debian.org/d/decompyle.html). As
it worked on Python 2.2 only long after Python 2.3 and 2.4 were in
widespread use, it was removed.
While John Aycock and Hartmut Goebel were well versed in compiler technology, those that have come afterwards don't seem to have been as facile in it. Furthermore, documentation or guidance on how the decompiler code worked, comparison to a conventional compiler pipeline, how to add new constructs, or debug grammars was weak. Some of the grammar tracing and error reporting was a bit weak as well.
[Crazy Compilers](http://www.crazy-compilers.com/decompyle/) offers a
byte-code decompiler service for versions of Python up to 2.6. As
someone who worked in compilers, it is tough to make a living by
working on compilers. (For example, based on
[John Aycock's recent papers](http://pages.cpsc.ucalgary.ca/~aycock/)
it doesn't look like he's done anything compiler-wise since SPARK). So
I hope people will use the crazy-compilers service. I wish them the
success that his good work deserves.
Given this, perhaps it is not surprising that subsequent changes tended to shy away from using the built-in compiler technology mechanisms and addressed problems and extensions by some other means.
Dan Pascu did a bit of work from late 2004 to early 2006 to get this
code to handle first Python 2.3 and then 2.4 bytecodes. Because of
jump optimization introduced in the CPython bytecode compiler at that
time, various JUMP instructions were classified to assist parsing For
example, due to the way that code generation and line number table
work, jump instructions to an earlier offset must be looping jumps,
such as those found in a "continue" statement; "COME FROM"
instructions were reintroduced. See
[RELEASE-2.4-CHANGELOG.txt](https://github.com/rocky/python-uncompyle6/blob/master/DECOMPYLE-2.4-CHANGELOG.txt)
for more details here. There wasn't a public release of RELEASE-2.4
and bytecodes other than Python 2.4 weren't supported. Dan says the
Python 2.3 version could verify the entire Python library. But given
subsequent bugs found like simply recognizing complex-number constants
in bytecode, decompilation wasn't perfect.
Specifically, in `uncompyle`, decompilation of python bytecode 2.5 & 2.6 is done by transforming the byte code into a pseudo-2.7 Python bytecode and is based on code from Eloi Vanderbeken. A bit of this could have been easily added by modifying grammar rules.
Next we get to ["uncompyle" and
PyPI](https://pypi.python.org/pypi/uncompyle/1.1) and the era of
public version control. (Dan's code although not public used
[darcs](http://darcs.net/) for version control.)
In contrast to _decompyle_, _uncompyle_ at least in its final versions,
runs only on Python 2.7. However it accepts bytecode back to Python
2.5. Thomas Grainger is the package owner of this, although Hartmut is
still listed as the author.
# uncompyle2, uncompyle3, uncompyle6
The project exists not only on
[github](https://github.com/gstarnberger/uncompyle) but also on
[bitbucket](https://bitbucket.org/gstarnberger/uncompyle) and later
the defunct [google
code](https://code.google.com/archive/p/unpyc/). The git/svn history
goes back to 2009. Somewhere in there the name was changed from
"decompyle" to "unpyc" by Keknehv, and then to "uncompyle" by Guenther Starnberger.
`Uncompyle6`, which I started in 2015, owes its existence to the fork of [uncompyle2](https://github.com/Mysterie/uncompyle2) by Myst herie (Mysterie) whose first commit picks up at 2012. I chose this since it seemed to have been at that time the most actively, if briefly, worked on. Also starting around 2012 is Dark Fenx's [uncompyle3](https://github.com/DarkFenX/uncompyle3) which I used for inspiration for Python3 support.
The name Thomas Grainger isn't found in (m)any of the commits in the
several years of active development. First Keknehv worked on this up
to Python 2.5 or so while acceping Python bytecode back to 2.0 or
so. Then hamled made a few commits earler on, while Eike Siewertsen
made a few commits later on. But mostly wibiti, and Guenther
Starnberger got the code to where uncompyle2 was around 2012.
While John Aycock and Hartmut Goebel were well versed in compiler
technology, those that have come afterwards don't seem to have been as
facile in it. Furthermore, documentation or guidance on how the
decompiler code worked, comparison to a conventional compiler
pipeline, how to add new constructs, or debug grammars was weak. Some
of the grammar tracing and error reporting was a bit weak as well.
Given this, perhaps it is not surprising that subsequent changes
tended to shy away from using the built-in compiler technology
mechanisms and addressed problems and extensions by some other means.
Specifically, in `uncompyle`, decompilation of python bytecode 2.5 &
2.6 is done by transforming the byte code into a pseudo-2.7 Python
bytecode and is based on code from Eloi Vanderbeken. A bit of this
could have been easily added by modifying grammar rules.
This project, `uncompyle6`, abandons that approach for various
reasons. Having a grammar per Python version is much cleaner and it
scales indefinitely. That said, we don't have entire copies of the
grammar, but work off of differences from some neighboring version.
Should there be a desire to rebase or start a new base version to work
off of, say for some future Python version, that can be done by
dumping a grammar for a specific version after it has been loaded
incrementally. You can get a full dump of the grammar by profiling the
grammar on a large body of Python source code.
Another problem with pseudo-2.7 bytecode is that that we need offsets
in fragment deparsing to be exactly the same as the bytecode; the
transformation process can remove instructions. _Adding_ instructions
with psuedo offsets is however okay.
`Uncompyle6` however owes its existence to the fork of `uncompyle2` by
Myst herie (Mysterie) whose first commit picks up at
2012. I chose this since it seemed to have been at that time the most
actively, if briefly, worked on. Also starting around 2012 is Dark
Fenx's uncompyle3 which I used for inspiration for Python3 support.
I started working on this late 2015, mostly to add fragment support.
In that, I decided to make this runnable on Python 3.2+ and Python 2.6+
while, handling Python bytecodes from Python versions 2.5+ and
3.2+. In doing so, it has been expedient to separate this into three
projects:
I started working on this late 2015, mostly to add fragment support. In that, I decided to make this runnable on Python 3.2+ and Python 2.6+ while handling Python bytecodes from Python versions 2.5+ and
3.2+. In doing so, it was expedient to separate this into three projects:
* marshaling/unmarshaling, bytecode loading and disassembly ([xdis](https://pypi.python.org/pypi/xdis)),
* parsing and tree building ([spark_parser](https://pypi.python.org/pypi/spark_parser)),
* this project - grammar and semantic actions for decompiling
([uncompyle6](https://pypi.python.org/pypi/uncompyle6)).
`uncompyle6`, abandons the idea found in some 2.7 version of `uncompyle` that support Python 2.6 and 2.5 by trying to rewrite opcodes at the bytecode level.
Over the many years, code styles and Python features have
changed. However brilliant the code was and still is, it hasn't really
had a single public active maintainer. And there have been many forks
of the code. I have spent a great deal of time trying to organize and
modularize the code so that it can handle more Python versions more
gracefully (with still only moderate success).
Having a grammar per Python version is simpler to maintain, cleaner and it scales indefinitely.
That it has been in need of an overhaul has been recognized by the
Hartmut a decade an a half ago:
Over the many years, code styles and Python features have changed. However brilliant the code was and still is, it hasn't really had a single public active maintainer. And there have been many forks of the code.
That this code has been in need of an overhaul has been recognized by the Hartmut more than two decades ago.
[decompyle/uncompile__init__.py](https://github.com/gstarnberger/uncompyle/blob/master/uncompyle/__init__.py#L25-L26)
NB. This is not a masterpiece of software, but became more like a hack.
Probably a complete rewrite would be sensefull. hG/2000-12-27
This project deparses using an Earley-algorithm parse with lots of
massaging of tokens and the grammar in the scanner
phase. Earley-algorithm parsers are context free and tend to be linear
if the grammar is LR or left recursive. There is a technique for
improving LL right recursion, but our parser doesn't have that yet.
In 2021, I created three git branches in order to allow the decompiler to run on a wide variety of Python versions from 2.4 up to 3.10. (Note this doesn't mean we decompile these versions. In fact we decompile starting from Python 1.0 up to Python 3.8 and no later than that.)
Another approach to decompiling, and one that doesn't use grammars is
to do something like simulate execution symbolically and build
expression trees off of stack results. Control flow in that approach
still needs to be handled somewhat ad hoc. The two important projects
that work this way are [unpyc3](https://code.google.com/p/unpyc3/) and
most especially [pycdc](https://github.com/zrax/pycdc) The latter
project is largely by Michael Hansen and Darryl Pogue. If they
supported getting source-code fragments, did a better job in
supporting Python more fully, and had a way I could call it from
Python, I'd probably would have ditched this and used that. The code
runs blindingly fast and spans all versions of Python, although more
recently Python 3 support has been lagging. The code is impressive for
its smallness given that it covers many versions of Python. However, I
think it has reached a scalability issue, same as all the other
efforts. To handle Python versions more accurately, I think that code
base will need to have a lot more code specially which specializes for
Python versions. And then it will run into a modularity problem.
Using the separate git branches allows me to continually improve the coding style and add feature support while still supporting older Pythons. Supporting older Pythons is nice (but not strictly necessary) when you want to debug decompilation on older Pythons.
Tests for the project have been, or are being, culled from all of the
projects mentioned. Quite a few have been added to improve grammar
coverage and to address the numerous bugs that have been encountered.
I have spent a great deal of time trying to organize, modularize and even modernize the code so that it can handle more Python versions more gracefully (with still only moderate success).
If you think, as I am sure will happen in the future, "hey, I can just
write a decompiler from scratch and not have to deal with all all of
the complexity here", think again. What is likely to happen is that
you'll get at best a 90% solution working for a single Python release
that will be obsolete in about a year, and more obsolete each
subsequent year. Writing a decompiler for Python gets harder as it
Python progresses, so writing one for Python 3.7 isn't as easy as it
was for Python 2.2. That said, if you still feel you want to write a
single version decompiler, look at the test cases in this project and
talk to me. I may have some ideas.
Tests for the project have been, or are being, culled from all of the projects mentioned above or below. Quite a few have been added to improve grammar coverage and to address the numerous bugs that have been encountered.
For a little bit of the history of changes to the Earley-algorithm parser,
see the file [NEW-FEATURES.rst](https://github.com/rocky/python-spark/blob/master/NEW-FEATURES.rst) in the [python-spark github repository](https://github.com/rocky/python-spark).
# unpyc3 and pydc
NB. If you find mistakes, want corrections, or want your name added
(or removed), please contact me.
Another approach to decompiling, and one that doesn't use grammars is to do something like simulate execution symbolically and build expression trees off of stack results. Control flow in that approach
still needs to be handled somewhat ad hoc. The two important projects that work this way are [unpyc3](https://code.google.com/p/unpyc3/) and most especially [pycdc](https://github.com/zrax/pycdc) The latter
project is largely by Michael Hansen and Darryl Pogue. If they supported getting source-code fragments, did a better job in supporting Python more fully, and had a way I could call it from Python, I'd probably would have ditched this and used that. The code runs blindingly fast and spans all versions of Python, although more recently Python 3 support has been lagging. The code is impressive for its smallness given that it covers many versions of Python. However, I think it has reached a scalability issue, same as all the other efforts. To handle Python versions more accurately, I think that code base will need to have a lot more code specially which specializes for Python versions. And then it will run into a modularity problem.
# So you want to write a decompiler for Python?
If you think, as I am sure will happen in the future, "hey, I can just write a decompiler from scratch and not have to deal with all of the complexity in uncompyle6", think again. What is likely to happen is that you'll get at best a 90% solution working for a single Python release that will be obsolete in about a year, and more obsolete each subsequent year.
Writing a decompiler for Python gets harder as it Python progresses. Writing decompiler for Python 3.7 isn't as easy as it was for Python 2.2. For one thing, now that Python has a well-established AST, that opens another interface by which code can be improved.
In Python 3.10 I am seeing (for the first time?) bytecode getting moved around so that it is no longer the case that line numbers have to be strictly increasing as bytecode offsets increase. And I am seeing dead code appear as well.
That said, if you still feel you want to write a single version decompiler, look at the test cases in this project and talk to me. I may have some ideas that I haven't made public yet. See also what I've written about the on how this code works and on [decompilation in dynamic runtime languages](http://rocky.github.io/Deparsing-Paper.pdf) in general.
# Earley Algorithm Parser
This project deparses using an Earley-algorithm parse. But in order to do this accurately, the process of tokenization is a bit more involved in the scanner. We don't just disassemble bytecode and use the opcode name. That aspect hasn't changed from the very first decompilers. However understanding _what_ information needs to be made explicit and what pseudo instructions to add that accomplish this has taken some time to understand.
Earley-algorithm parsers have gotten negative press, most notably by the dragon book. Having used this a bit, I am convinced having a system that handles ambiguous grammars is the right thing to do and matches the problem well. In practice the speed of the parser isn't a problem when one understand what's up. And this has taken a little while to understand.
Earley-algorithm parsers for context free languages or languages that are to a large extent context free and tend to be linear and the grammar steers towards left recursive rules. There is a technique for improving LL right recursion, but our parser doesn't have that yet.
The [decompiling paper](http://rocky.github.io/Deparsing-Paper.pdf) discusses these aspects in a more detail.
For a little bit of the history of changes to the Earley-algorithm parser, see the file [NEW-FEATURES.rst](https://github.com/rocky/python-spark/blob/master/NEW-FEATURES.rst) in the [python-spark github repository](https://github.com/rocky/python-spark).
NB. If you find mistakes, want corrections, or want your name added (or removed), please contact me.

View File

@@ -1,60 +1,66 @@
<!-- markdown-toc start - Don't edit this section. Run M-x markdown-toc-refresh-toc -->
**Table of Contents**
- [The difficulty of the problem](#the-difficulty-of-the-problem)
- [Ethics](#ethics)
- [The importance of your bug report](#the-importance-of-your-bug-report)
- [The difficulty of the problem and your bug](#the-difficulty-of-the-problem-and-your-bug)
- [Is it really a bug?](#is-it-really-a-bug)
- [Do you have valid bytecode?](#do-you-have-valid-bytecode)
- [Semantic equivalence vs. exact source code](#semantic-equivalence-vs-exact-source-code)
- [What to send (minimum requirements)](#what-to-send-minimum-requirements)
- [What to send (additional helpful information)](#what-to-send-additional-helpful-information)
- [But I don't *have* the source code!](#but-i-dont-have-the-source-code)
- [But I don't *have* the source code and am incapable of figuring how how to do a hand disassembly!](#but-i-dont-have-the-source-code-and-am-incapable-of-figuring-how-how-to-do-a-hand-disassembly)
- [But I don't *have* the source code and am incapable of figuring how to do a hand disassembly!](#but-i-dont-have-the-source-code-and-am-incapable-of-figuring-how-to-do-a-hand-disassembly)
- [Narrowing the problem](#narrowing-the-problem)
- [Karma](#karma)
- [Confidentiality of Bug Reports](#confidentiality-of-bug-reports)
- [Ethics](#ethics)
<!-- markdown-toc end -->
# The difficulty of the problem
TL;DR (too long; didn't read)
* Don't do something illegal. And don't ask me to do something illegal or help you do something illegal.
* We already have an infinite supply of decompilation bugs that need fixing, and an automated mechanism for finding more. Decompilation bugs get addressed by easiness to fix and by whim. If you expect yours to be fixed ahead of those, you need to justify why. You can ask for a hand-assisted decompilation, but that is expensive and beyond what most are willing to spend. A $100 fee is needed just to look at the bytecode.
* When asking for help, you may be asked for what you've tried on your own first. There are plenty of sources of information about this code.
* Bugs get fixed, slowly. Sometimes on the order of months or years. If you are looking for *timely* help or support, that is typically known as a _paid_ service.
* Submitting a bug or issue report that is likely to get acted upon may require a bit of effort on your part to make it easy for the problem solver. If you are not willing to do that, please don't waste your or our time. Bug report may be closed with about as much thought and care as apparent in the effort to create the bug. Supporting the project however, does increase the likelihood of your issue getting noticed and acted upon.
# Ethics
Do not use this program for unethical or illegal purposes. More detestable, at least to me, is asking for help to assist you in something that might not legitimate.
Don't use the issue tracker for such unethical or illegal solicitations. To try to stave off illegitimate behavior, you should note that the issue tracker, the code, and bugs mentioned in that are in the open: there is no
confidentiality. You may be asked about the authorship or claimed ownership of the bytecode. If I think something is not quite right, I may label the issue questionable which may make the it easier those who are looking for illegal activity.
# The importance of your bug report
For many open-source projects bugs where the expectation is that bugs are rare, reporting bugs in a *thoughtful* way can be helpful. See also [How to Ask Questions the Smart Way](http://www.catb.org/~esr/faqs/smart-questions.html).
In this project though, most of the bug reports boil down to the something like: I am trying to reverse engineer some code that I am not the author/owner and that person doesn't want me to have access to. I am hitting a problem somewhere along the line which might have to do with decompilation. But it could be something else like how the bytecode was extracted, some problem in deliberately obfuscated code, or the use some kind of Python bytecode version that isn't supported by the decompiler. Gee this stuff is complicated, here's an open source project, so maybe someone there will help me figure stuff out.
While you are free to report bugs, unless you sponsor the project, I may close them with about the same amount of effort spent that I think was used to open the report for them. And if you spent a considerable amount of time to create the bug report but didn't follow instructions given here and in the issue template, I am sorry in advance. Just go back, read, and follow instructions.
This project already has an infinite supply of bugs that have been narrowed to the most minimal form and where I have source code to compare against. And in the unlikely event this supply runs out, I have automated means for generating *another* infinite supply.
The task of justifying why addressing your bug is of use to the community, and why it should be prioritized over the others, is the bug reporter's responsibility.
While in the abstract, I have no problem answering questions about how to read a Python traceback or install Python software, or trying to understand what is going wrong in your particular setup, I am not a paid support person and there other things I'd rather be doing with my limited volunteer time. So save us both time, effort, and aggravation: use other avenues like StackOverflow. Again, justifying why you should receive unpaid help is the help requester's responsibility.
# The difficulty of the problem and your bug
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. And if your bug hasn't been narrowed, it might happen as a result of some other bug fix.
# Is it really a bug?
@@ -62,28 +68,17 @@ 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, release candidates, and the most recent versions of Python: version 3.9 and up. See README.rst for suggestions for how to remove some kinds of
obfuscation.
Checking if bytecode is valid is pretty simple: disassemble the code.
Python comes with a disassembly module called `dis`. A prerequisite
module for this package, `xdis` has a cross-python version
disassembler called `pydisasm`.
disassembler called `pydisasm`. Using that with the `-F extended` option, generally provides a more comprehensive disassembly than is provided by other disassemblers.
## Semantic equivalence vs. exact source code
Consider how Python compiles something like "(x*y) + 5". Early on
Python creates an "abstract syntax tree" (AST) for this. And this is
"abstract" in the sense that unimportant, redundant or unnecessary
items have been removed. Here, this means that any notion that you
wrote "x+y" in parenthesis is lost, since in this context they are
unneeded. Also lost is the fact that the multiplication didn't have
spaces around it while the addition did. It should not come as a
surprise then that the bytecode which is derived from the AST also has
no notion of such possible variation. Generally this kind of thing
isn't noticed since the Python community has laid out a very rigid set
of formatting guidelines; and it has largely beaten the community into
compliance.
Consider how Python compiles something like "(x*y) + 5". Early on Python creates an "abstract syntax tree" (AST) for this. And this is "abstract" in the sense that unimportant, redundant or unnecessary items have been removed. Here, this means that any notion that you wrote "x+y" in parenthesis is lost, since in this context they are unneeded. Also lost is the fact that the multiplication didn't have spaces around it while the addition did. It should not come as a surprise then that the bytecode which is derived from the AST also has no notion of such possible variation. Generally this kind of thing isn't noticed since the Python community has laid out a very rigid set of formatting guidelines; and it has largely beaten the community into compliance.
Almost all versions of Python can perform some sort of code
improvement that can't be undone. In earlier versions of Python it is
@@ -144,8 +139,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)
@@ -166,7 +160,7 @@ Also try to narrow the bug. See below.
Some kind folks also give the invocation they used and the output
which usually includes an error message produced. This is
helpful. From this, I can figure out what OS you are running this on
and what version of *uncomplye6* was used. Therefore, if you _don't_
and what version of *uncompyle6* was used. Therefore, if you _don't_
provide the input command and the output from that, please give:
* _uncompyle6_ version used
@@ -176,30 +170,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.) Don't be surprised if I ask you to pay for work (if I think the work is ethical) when you want me to work on your problem that I think isn't of interest or benefit to anyone but yourself or a small limited number of people, or I think the need is questionable.
# 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,33 +199,29 @@ 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
in the category of bug fixers.
burden on the bug reporter. This is justified since it attempts to balance
the burden and effort needed to fix the bug with the amount of effort to report the problem. And it 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
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 ...
* 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.
great favor by just pointing out that there is a problem whose
solution would greatly benefit them. (This might account partially
for the fact that those that have this attitude often don't read or
follow instructions such as those given here.)
# Confidentiality of Bug Reports
@@ -255,16 +233,6 @@ remains would not be an issue.
However feel free to remove any comments, and modify variable names
or constants in the source code.
# Ethics
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.
I do not condone using this program for unethical or illegal purposes.
More detestable, at least to me, is asking for help to assist you in
something that might not legitimate.
Don't use the issue tracker for such solicitations. To try to stave
off illegitimate behavior, you should note that the issue tracker, the
code, and bugs mentioned in that are in the open: there is no
confidentiality. You may be asked about the authorship or claimed
ownership of the bytecode. If I think something is not quite right, I
may label the issue questionable which may make the it easier those
who are looking for illegal activity.
Private consulting available via https://calendly.com/rb3216 rates: $150 for 30 minutes; $250 for 60 minutes.

View File

@@ -11,7 +11,10 @@ RM ?= rm
LINT = flake8
#EXTRA_DIST=ipython/ipy_trepan.py trepan
PHONY=all check clean distcheck pytest check-long dist distclean lint flake8 test rmChangeLog clean_pyc
PHONY=all check check-2.7 check-3.4 \
clean distcheck pytest check-long check-short \
dist distclean lint flake8 test rmChangeLog clean_pyc \
2.6 5.0 5.3 5.6 5.8 7.2 7.3 check-short
TEST_TYPES=check-long check-short check-2.7 check-3.4
@@ -51,8 +54,12 @@ check-3.8:
7.1 pypy-3.2 2.4:
$(MAKE) -C test $@
#:PyPy pypy3-2.4.0 Python 3.6.9:
7.2:
#:PyPy versions
7.2 7.3:
$(MAKE) -C test $@
#:pyston versions
2.3:
$(MAKE) -C test $@
#: Run py.test tests

141
NEWS.md
View File

@@ -1,3 +1,112 @@
3.9.2: 2024-07-21
=================
- track xdis API changes
- Bug fixes and lint
3.9.1: 2024-05-15
=================
Lots of changes major changes. track xdis API has changes.
Separate Phases more clearly:
* disassembly
* tokenization
* parsing
* abstracting to AST (more is done in newer projects)
* printing
Although we do not decompile bytecode greater than 3.8, code supports running from up to 3.12.
Many bugs fixed.
A lot of Linting and coding style modernization.
Work done in preparation for Blackhat Asia 2024
3.9.0: 2022-12-22
=================
* deparse generator expressions for Python 3.0 .. 3.2
* Python 3.0 list comprehension.
* Fix Issues #310, #344, #377, #391, #409, #414
* Limited support for 3.8+ f-string "=" specifier
* Correct 2.5-7 relative import formatting
* Miscellaneous bug fixing
* remove \n in lambda
* Python 2.6 grammar cleanup
* Correct some Python 2.6 chain compare decompilation
* Ensure no parenthesis subscript slices
* Correct 2.x formatting "slice2" nonterminal
* Correct 3.7 imports
* Improve "async for" parsing
* Handle BUILD_MAP opcode
* match Python AT better
* Correct 3.7 positional args
* PyPy 3.7 and PyPy 3.8 support
* Miscellaneous linting, isorting, blacking
3.8.0: 2021-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 statement
* 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
====================================================
Released to pick up new xdis version which has fixes to read bytestrings better on 3.x
* Handle 3.7+ "else" branch removal adAs seen in `_cmp()` of `python3.8/distutils/version.py` with optimization `-O2`
* 3.6+ "with" and "with .. as" grammar improvements
* ast-check for "for" loop was missing some grammar rules
3.7.0: 2020-5-19 Primidi 1st Prairial - Alfalfa - HF
====================================================
The main impetus for this release is to pull in the recent changes from xdis.
We simplify imports using xdis 4.6.0.
There were some bugfixes to Python 3.4-3.8. See the ChangeLog for details
3.6.7: 2020-4-27 xdis again
===========================
@@ -6,10 +115,10 @@ More upheaval in xdis which we need to track here.
3.6.6: 2020-4-20 Love in the time of Cholera
============================================
The main reason for this release is an incompatablity bump in xdis which handles
The main reason for this release is an incompatibility bump in xdis which handles
3.7 SipHash better.
* Go over "yield" as an expression precidence
* Go over "yield" as an expression precedence
* Some small alignment with code in decompyle3 for "or" and "and" was done
@@ -35,7 +144,7 @@ The main focus in this release was fix some of the more glaring problems creapt
`uncompyle6` code is at a plateau where what is most needed is a code refactoring. In doing this, until everything refactored and replaced, decomplation may get worse.
Therefore, this release largely serves as a checkpoint before more major upheaval.
The upheaval, in started last release, I believe the pinnicle was around c90ff51 which wasn't a release. I suppose I should tag that.
The upheaval, in started last release, I believe the pinnacle was around c90ff51 which wasn't a release. I suppose I should tag that.
After c90ff5, I started down the road of redoing control flow in a more comprehensible, debuggable, and scalable way. See [The Control Flow Mess](https://github.com/rocky/python-uncompyle6/wiki/The-Control-Flow-Mess)
@@ -49,7 +158,7 @@ In the decompyle3 code, I've gone down the road making the grammar goal symbol b
I cringe in thinking about how the code has lived for so long without noticing such a simple stupidity, and lapse of sufficient thought.
Some stats from testing. The below give numbers of decompiled tests from Python's test suite which succesfully ran
Some stats from testing. The below give numbers of decompiled tests from Python's test suite which successfully ran
```
Version test-suites passing
@@ -92,14 +201,14 @@ On the most recent Python versions I regularly decompile thousands of Python pro
Does this mean the decompiler works perfectly? No. There are still a dozen or so failing programs, although the actual number of bugs is probably smaller though.
However, in perparation of a more major refactoring of the parser grammar, this release was born.
However, in preparation of a more major refactoring of the parser grammar, this release was born.
In many cases, decompilation is better. But there are some cases where decompilation has gotten worse. For lack of time (and interest) 3.0 bytecode suffered a hit. Possibly some code in the 3.x range did too. In time and with cleaner refactored code, this will come back.
Commit c90ff51 was a local maxiumum before, I started reworking the grammar to separate productions that were specific to loops versus those that are not in loops.
In the middle of that I added another grammar simplication to remove singleton productions of the form `sstmts-> stmts`. These were always was a bit ugly, and complicated output.
Commit c90ff51 was a local maximum before, I started reworking the grammar to separate productions that were specific to loops versus those that are not in loops.
In the middle of that I added another grammar simplification to remove singleton productions of the form `sstmts-> stmts`. These were always was a bit ugly, and complicated output.
At any rate if decompilation fails, you can try c90ff51. Or another decompiler. `unpyc37` is pretty good for 3.7. wibiti `uncompyle2` is great for 2.7. `pycdc` is mediocre for Python before 3.5 or so, and not that good for the most recent Python. Geerally these programs will give some sort of answer even if it isn't correct.
At any rate if decompilation fails, you can try c90ff51. Or another decompiler. `unpyc37` is pretty good for 3.7. wibiti `uncompyle2` is great for 2.7. `pycdc` is mediocre for Python before 3.5 or so, and not that good for the most recent Python. Generally these programs will give some sort of answer even if it isn't correct.
decompyle3 isn't that good for 3.7 and worse for 3.8, but right now it does things no other Python decompiler like `unpyc37` or `pycdc` does. For example, `decompyle3` handles variable annotations. As always, the issue trackers for the various programs will give you a sense for what needs to be done. For now, I've given up on reporting issues in the other decompilers because there are already enough issues reported, and they are just not getting fixed anyway.
@@ -130,7 +239,7 @@ indicate when an import contains a dotted import. Similarly, code for
3.7 `import .. as ` is basically the same as `from .. import`, the
only difference is the target of the name changes to an "alias" in the
former. As a result, the disambiguation is now done on the semantic
action side, rathero than in parsing grammar rules.
action side, rather than in parsing grammar rules.
Some small specific fixes:
@@ -163,13 +272,13 @@ versions better. This however comes with a big decompilation speed
penalty. When we redo control flow this should go back to normal, but
for now, accuracy is more important than speed.
Another `assert` transform rule was added. Parser rules to distingish
Another `assert` transform rule was added. Parser rules to distinguish
`try/finally` in 3.8 were added and we are more stringent about what
can be turned into an `assert`. There was some grammar cleanup here
too.
A number of small bugs were fixed, and some administrative changes to
make `make check-short` really be short, but check more throughly what
make `make check-short` really be short, but check more thoroughly what
it checks. minimum xdis version needed was bumped to include in the
newer 3.6-3.9 releases. See the `ChangeLog` for details.
@@ -178,7 +287,7 @@ newer 3.6-3.9 releases. See the `ChangeLog` for details.
=============================
The main focus in this release was more accurate decompilation especially
for 3.7 and 3.8. However there are some improvments to Python 2.x as well,
for 3.7 and 3.8. However there are some improvements to Python 2.x as well,
including one of the long-standing problems of detecting the difference between
`try ... ` and `try else ...`.
@@ -186,11 +295,11 @@ With this release we now rebase Python 3.7 on off of a 3.7 base; This
is also as it is (now) in decompyle3. This facilitates removing some of the
cruft in control-flow detection in the 2.7 uncompyle2 base.
Alas, decompilation speed for 3.7 on is greatly increased. Hopefull
Alas, decompilation speed for 3.7 on is greatly increased. Hopefully
this is temporary (cough, cough) until we can do a static control flow
pass.
Finally, runing in 3.9-dev is tolerated. We can disassemble, but no parse tables yet.
Finally, running in 3.9-dev is tolerated. We can disassemble, but no parse tables yet.
3.5.1 2019-11-17 JNC
@@ -483,7 +592,7 @@ function calls and definitions.
- Misc pydisasm fixes
- Weird comprehension bug seen via new loctraceback
- Fix Python 3.5+ CALL_FUNCTION_VAR and BUILD_LIST_UNPACK in call; with this
we can can handle 3.5+ f(a, b, *c, *d, *e) now
we can handle 3.5+ f(a, b, *c, *d, *e) now
2.15.1 2018-02-05
=====================
@@ -578,7 +687,7 @@ Overall: better 3.6 decompiling and some much needed code refactoring and cleanu
- Handle `EXTENDED_ARGS` better. While relevant to all Python versions it is most noticeable in
version 3.6+ where in switching to wordcodes the size of operands has been reduced from 2^16
to 2^8. `JUMP` instruction then often need EXTENDED_ARGS.
- Refactor find_jump_targets() with via working of of instructions rather the bytecode array.
- Refactor find_jump_targets() with via working of instructions rather the bytecode array.
- use `--weak-verify` more and additional fuzzing on verify()
- fragment parser now ignores errors in nested function definitions; an parameter was
added to assist here. Ignoring errors may be okay because the fragment parser often just needs,

221
NEW_FEATURES.rst Normal file
View File

@@ -0,0 +1,221 @@
Introduction
============
The original versions of this code up until the time I started were
pretty awesome. You can get a sense of this by running it. For the
most part it was remarkably fast, and a single module with few dependencies.
Here I will largely give what are the major improvements over old code.
This also serves to outline a little bit about what is in this code.
See also `How does this code work? <https://github.com/rocky/python-uncompyle6/wiki/How-does-this-code-work%3F>`_.
Old Cool Features
==================
Before getting to the new stuff, I'll describe cool things that was there before.
I particularly liked the ability to show the assembly, grammar
reduction rules as they occurred, and the resulting parse tree. It is
neat that you could follow the process and steps that deparser takes,
and in this not only see the result how the bytecode corresponds to
the resulting source. Compare this with other Python decompilers.
And of course also neat was that this used a grammar and table-driven
approach to decompile.
Expanding decompilation to multiple Python Versions
==================================================
Aside from ``pycdc``, most of the Python decompilers handle a small
number of Python versions, if they supported more than one. And even
when more than one version is supported if you have to be running the
Python version that the bytecode was compiled for.
There main reason that you have to be running the Python bytecode
interpreter as the one you want to decompile largely stems from the
fact that Python's ``dis`` module is often what is used and that has this limitation.
``pycdc`` doesn't suffer this problem because it is written in C++,
not Python. Hartmut Goebel's code had provisions for multiple Python
versions running from an interpreter different from the one that was
running the decompiler. That however used compiled code in the process
was tied a bit to the Python C headers for a particular version.
You need to not only to account for different "marshal" and "unmarshal"
routines for the different Python versions, but also, as the Python versions
extend, you need a different code type as well.
Enter ``xdis``
--------------
To handle all of these problems, I split off the marshal loading
portion and disassembly routines into a separate module,
`xdis <https://pypi.org/project/xdis/>`_. This also allows older Pythons to have access to features
found in newer Pythons, such as parsing the bytecode, a uniform stream
of bytes, into a list of structured bytecode instructions.
Python 2.7's ``dis`` module doesn't has provide a instruction abstraction.
Therefore in ``uncompyle2`` and other earlier decompilers you see code with magic numbers like 4 in::
if end > jump_back+4 and code[end] in (JF, JA):
if code[jump_back+4] in (JA, JF):
if self.get_target(jump_back+4) == self.get_target(end):
self.fixed_jumps[pos] = jump_back+4
end = jump_back+4
elif target < pos:
self.fixed_jumps[pos] = jump_back+4
end = jump_back+4
and in other code -1 and 3 in::
if self.get_target(jmp) != start_else:
end_else = self.get_target(jmp)
if self.code[jmp] == JF:
self.fixed_jumps[jmp] = -1
self.structs.append({'type': 'except',
'start': i,
'end': jmp})
i = jmp + 3
All of that offset arithmetic is trying to find the next instruction
offset or the previous offset. Using a list of instructions you simply
take the ``offset`` field of the previous or next instruction.
The above code appears in the ``uncompyle2`` "Scanner" class in
service of trying to figure out control flow. Note also that there
isn't a single comment in there about what specifically it is trying
to do, the logic or that would lead one to be confident that this is
correct, let alone assumptions that are needed for this to be true.
While this might largely work for Python 2.7, and ``uncompyle2`` does
get control flow wrong sometimes, it is impossible to adapt code for
other versions of Python.
In addition adding an instruction structure, ``xdis`` adds various
flags and features that assist in working with instructions. In the
example above this replaces code like ``... in (JF, JA)`` which is
some sort of unconditional jump instruction.
Although not needed in the decompiler, ``xdis`` also has nicer
instruction print format. It can show you the bytes as well as the
interpreted instructions. It will interpret flag bits and packed
structures in operands so you don't have to. It can even do a limited
form of inspection at previous instructions to give a more complete
description of an operand. For example on ``LOAD_ATTR`` which loads
the attribute of a variable, often the variable name can be found as
the previous instruction. When that is the case the disassembler can
include that in the disassembly display for the ``LOAD_ATTR`` operand.
Python Grammar Isolation
------------------------
If you want to support multiple versions of Python in a manageable way
you really need to provide different grammars for the different
versions, in a grammar-based system. None of the published versions of
this decompiler did this.
If you look at the changes in this code, right now there are no
grammar changes needed between 1.0 to 1.3. (Some of this may be wrong
though since we haven't extensively tested these earliest Python versions
For Python 1.4 which is based off of the grammar for 1.5 though there
are number of changes, about 6 grammar rules. Later versions of though
we start to see larger upheaval and at certain places, especially
those where new opcodes are introduced, especially those that change
the way calls or exceptions get handled, we have major upheaval in the
grammar. It is not just that some rules get added, but we also need to
*remove* some grammar rules as well.
I have been largely managing this as incremental differences between versions.
However in the future I am leaning more towards totally separate grammars.
A well constructed grammar doesn't need to be that large.
When starting out a new version, we can just copy the grammar from the
prior version. Within a Python version though, I am breaking these
into composable pieces. In particular the grammar for handling what
can appear as the body of a lambda, is a subset of the full Python
language. The language allowed in an ``eval`` is also a subset of the
full Python language, as are what can appear in the various
compilation modes like "single" versus "exec".
Another nice natural self-contain grammar section is what can appear
in list comprehensions and generators. The bodies of these are
generally represented in a self-contained code block.
Often in decompilation you may be interested not just in decompiling
the entire code but you may be interested in only focusing on a
specific part of the code. And if there is a problem in decompiling
the entire piece of code, having these smaller breaking points can be
of assistance.
Other Modularity
----------------
Above we have mentioned the need for separate grammars or to isolate
these per versions. But there are other major pieces that make up this
decompiler. In particular there is a scanner and the source code
generation part.
Even though differences in version that occur in disassembly are
handled by ``xdis``, we still have to do conversion of that to a token
stream for parsing. So the scanners are again broken out per version
with various OO mechanisms for reusing code. The same is true for
source code generation.
Expanding decompiler availability to multiple Python Versions
--------------------------------------------------------------
Above we mention decompiling multiple versions of bytecode from a
single Python interpreter. We talk about having the decompiler
runnable from multiple versions of Python, independent of the set of
bytecode that the decompiler supports.
There are slight advantages in having a decompiler that runs the same
version as the code you are decompiling. The most obvious one is that
it makes it easy to test to see whether the decompilation correct
because you can run the decompiled code. Python comes with a suite of
Python programs that check themselves and that aspects of Python are
implemented correctly. These also make excellent programs to check
whether a program has decompiled correctly.
Aside from this, debugging can be easier as well. To assist
understanding bytecode and single stepping it see `x-python
<https://pypi.org/project/x-python/>`_ and the debugger for it
`trepan-xpy <https://pypi.org/project/trepanxpy/>`_.
Handling Language Drift
-----------------------
Given the desirability of having this code running on logs of Python
versions, how can we get this done?
The solution used here is to have several git branches of the
code. Right now there are 3 branches. Each branch handles works across
3 or so different releases of Python. In particular one branch handles
Python 2.4 to 2.7 Another handles Python 3.3 to 3.5, and the master
branch handles 3.6 to 3.10. (Again note that the 3.9 and 3.10
decompilers do not decompile Python 3.9 or 3.10, but they do handle
bytecode for all earlier versions.)
Cool features of the Parser
===========================
* reduction rule checking
* numbering tokens
* showing a stack of completions
Cool features Semantic Analysis
===============================
* ``--tree++`` (``-T``) option
* showing precedence
* See `Adding a tree transformation phase to uncompyle6 <https://github.com/rocky/python-uncompyle6/wiki/Adding-a-tree-transformation-phase-to-uncompyle6>`_
* following AST
* Fragment deparsing

359
PKG-INFO
View File

@@ -1,10 +1,355 @@
Metadata-Version: 2.0
Metadata-Version: 1.1
Name: uncompyle6
Version: 2.0.1
Summary: Python byte-code to source-code converter
Home-page: http://github.com/rocky/python-uncompyle6
Author: Rocky
Version: 3.9.1
Summary: Python cross-version byte-code decompiler
Home-page: https://github.com/rocky/python-uncompyle6/
Author: Rocky Bernstein, Hartmut Goebel, John Aycock, and others
Author-email: rb@dustyfeet.com
License: MIT
Description: UNKNOWN
License: GPL3
Description: |buildstatus| |Pypi Installs| |Latest Version| |Supported Python Versions|
|packagestatus|
.. contents::
uncompyle6
==========
A native Python cross-version decompiler and fragment decompiler.
The successor to decompyle, uncompyle, and uncompyle2.
Introduction
------------
*uncompyle6* translates Python bytecode back into equivalent Python
source code. It accepts bytecodes from Python version 1.0 to version
3.8, spanning over 24 years of Python releases. We include Dropbox's
Python 2.5 bytecode and some PyPy bytecodes.
Why this?
---------
Ok, I'll say it: this software is amazing. It is more than your
normal hacky decompiler. Using compiler_ technology, the program
creates a parse tree of the program from the instructions; nodes at
the upper levels that look a little like what might come from a Python
AST. So we can really classify and understand what's going on in
sections of Python bytecode.
Building on this, another thing that makes this different from other
CPython bytecode decompilers is the ability to deparse just
*fragments* of source code and give source-code information around a
given bytecode offset.
I use the tree fragments to deparse fragments of code *at run time*
inside my trepan_ debuggers_. For that, bytecode offsets are recorded
and associated with fragments of the source code. This purpose,
although compatible with the original intention, is yet a little bit
different. See this_ for more information.
Python fragment deparsing given an instruction offset is useful in
showing stack traces and can be incorporated into any program that
wants to show a location in more detail than just a line number at
runtime. This code can be also used when source-code information does
not exist and there is just bytecode. Again, my debuggers make use of
this.
There were (and still are) a number of decompyle, uncompyle,
uncompyle2, uncompyle3 forks around. Many of them come basically from
the same code base, and (almost?) all of them are no longer actively
maintained. One was really good at decompiling Python 1.5-2.3, another
really good at Python 2.7, but that only. Another handles Python 3.2
only; another patched that and handled only 3.3. You get the
idea. This code pulls all of these forks together and *moves
forward*. There is some serious refactoring and cleanup in this code
base over those old forks. Even more experimental refactoring is going
on in decompyle3_.
This demonstrably does the best in decompiling Python across all
Python versions. And even when there is another project that only
provides decompilation for subset of Python versions, we generally do
demonstrably better for those as well.
How can we tell? By taking Python bytecode that comes distributed with
that version of Python and decompiling these. Among those that
successfully decompile, we can then make sure the resulting programs
are syntactically correct by running the Python interpreter for that
bytecode version. Finally, in cases where the program has a test for
itself, we can run the check on the decompiled code.
We 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
------------
The code in the git repository can be run from Python 2.4 to the
latest Python version, with the exception of Python 3.0 through
3.2. Volunteers are welcome to address these deficiencies if there a
desire to do so.
The way it does this though is by segregating consecutive Python versions into
git branches:
master
Python 3.6 and up (uses type annotations)
python-3.3-to-3.5
Python 3.3 through 3.5 (Generic Python 3)
python-2.4
Python 2.4 through 2.7 (Generic Python 2)
PyPy 3-2.4 and later works as well.
The bytecode files it can read have been tested on Python
bytecodes from versions 1.4, 2.1-2.7, and 3.0-3.8 and later PyPy
versions.
Installation
------------
You can install from PyPI using the name ``uncompyle6``::
pip install uncompyle6
To install from source code, this project uses setup.py, so it follows the standard Python routine::
$ pip install -e . # set up to run from source tree
or::
$ python setup.py install # may need sudo
A GNU Makefile is also provided so :code:`make install` (possibly as root or
sudo) will do the steps above.
Running Tests
-------------
::
make check
A GNU makefile has been added to smooth over setting running the right
command, and running tests from fastest to slowest.
If you have remake_ installed, you can see the list of all tasks
including tests via :code:`remake --tasks`
Usage
-----
Run
::
$ uncompyle6 *compiled-python-file-pyc-or-pyo*
For usage help:
::
$ uncompyle6 -h
Verification
------------
In older versions of Python it was possible to verify bytecode by
decompiling bytecode, and then compiling using the Python interpreter
for that bytecode version. Having done this, the bytecode produced
could be compared with the original bytecode. However as Python's code
generation got better, this no longer was feasible.
If you want Python syntax verification of the correctness of the
decompilation process, add the :code:`--syntax-verify` option. However since
Python syntax changes, you should use this option if the bytecode is
the right bytecode for the Python interpreter that will be checking
the syntax.
You can also cross compare the results with another version of
`uncompyle6` since there are sometimes regressions in decompiling
specific bytecode as the overall quality improves.
For Python 3.7 and 3.8, the code in decompyle3_ is generally
better.
Or try specific another python decompiler like uncompyle2_, unpyc37_,
or pycdc_. Since the later two work differently, bugs here often
aren't in that, and vice versa.
There is an interesting class of these programs that is readily
available give stronger verification: those programs that when run
test themselves. Our test suite includes these.
And Python comes with another a set of programs like this: its test
suite for the standard library. We have some code in :code:`test/stdlib` to
facilitate this kind of checking too.
Known Bugs/Restrictions
-----------------------
The biggest known and possibly fixable (but hard) problem has to do
with handling control flow. (Python has probably the most diverse and
screwy set of compound statements I've ever seen; there
are "else" clauses on loops and try blocks that I suspect many
programmers don't know about.)
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 pretty good for Python 2
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 strongest around 3.4 or
3.3 and drops off as you move further away from those versions. Python
3.0 is weird in that it in some ways resembles 2.6 more than it does
3.1 or 2.7. Python 3.6 changes things drastically by using word codes
rather than byte codes. As a result, the jump offset field in a jump
instruction argument has been reduced. This makes the :code:`EXTENDED_ARG`
instructions are now more prevalent in jump instruction; previously
they had been rare. Perhaps to compensate for the additional
:code:`EXTENDED_ARG` instructions, additional jump optimization has been
added. So in sum handling control flow by ad hoc means as is currently
done is worse.
Between Python 3.5, 3.6, 3.7 there have been major changes to the
: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
make control-flow detection harder, lacking the more sophisticated
control-flow analysis that is planned. We'll see.
Currently not all Python magic numbers are supported. Specifically in
some versions of Python, notably Python 3.6, the magic number has
changes several times within a version.
**We support only released versions, not candidate versions.** Note
however that the magic of a released version is usually the same as
the *last* candidate version prior to release.
There are also customized Python interpreters, notably Dropbox,
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_ or otherwise obfuscated code. For
PJOrion try: PJOrion Deobfuscator_ to unscramble the bytecode to get
valid bytecode before trying this tool; pydecipher_ might help with that.
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. `Pydeinstaller <https://github.com/charles-dyfis-net/pydeinstaller>`_ may help with unpacking Pyinstaller bundlers.
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.
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. Volunteers are welcome to do so.
You may run across a bug, that you want to report. Please do so after
reading `How to report a bug
<https://github.com/rocky/python-uncompyle6/blob/master/HOW-TO-REPORT-A-BUG.md>`_ and
follow the `instructions when opening an issue <https://github.com/rocky/python-uncompyle6/issues/new?assignees=&labels=&template=bug-report.md>`_.
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
--------
* https://github.com/rocky/python-decompile3 : Much smaller and more modern code, focusing on 3.7 and 3.8. Changes in that will get migrated back here.
* https://code.google.com/archive/p/unpyc3/ : supports Python 3.2 only. The above projects use a different decompiling technique than what is used here. Currently unmaintained.
* https://github.com/figment/unpyc3/ : fork of above, but supports Python 3.3 only. Includes some fixes like supporting function annotations. Currently unmaintained.
* https://github.com/wibiti/uncompyle2 : supports Python 2.7 only, but does that fairly well. There are situations where :code:`uncompyle6` results are incorrect while :code:`uncompyle2` results are not, but more often uncompyle6 is correct when uncompyle2 is not. Because :code:`uncompyle6` adheres to accuracy over idiomatic Python, :code:`uncompyle2` can produce more natural-looking code when it is correct. Currently :code:`uncompyle2` is lightly maintained. See its issue `tracker <https://github.com/wibiti/uncompyle2/issues>`_ for more details.
* `How to report a bug <https://github.com/rocky/python-uncompyle6/blob/master/HOW-TO-REPORT-A-BUG.md>`_
* The HISTORY_ file.
* https://github.com/rocky/python-xdis : Cross Python version disassembler
* https://github.com/rocky/python-xasm : Cross Python version assembler
* https://github.com/rocky/python-uncompyle6/wiki : Wiki Documents which describe the code and aspects of it in more detail
* https://github.com/zrax/pycdc : The README for this C++ code says it aims to support all versions of Python. You can aim your slign shot for the moon too, but I doubt you are going to hit it. This code 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/trepan3k
.. _compiler: https://github.com/rocky/python-uncompyle6/wiki/How-does-this-code-work%3F
.. _HISTORY: https://github.com/rocky/python-uncompyle6/blob/master/HISTORY.md
.. _report_bug: https://github.com/rocky/python-uncompyle6/blob/master/HOW-TO-REPORT-A-BUG.md
.. _debuggers: https://pypi.python.org/pypi/trepan3k
.. _remake: https://bashdb.sf.net/remake
.. _pycdc: https://github.com/zrax/pycdc
.. _decompyle3: https://github.com/rocky/python-decompile3
.. _uncompyle2: https://github.com/wibiti/uncompyle2
.. _unpyc37: https://github.com/andrew-tavera/unpyc37
.. _this: https://github.com/rocky/python-uncompyle6/wiki/Deparsing-technology-and-its-use-in-exact-location-reporting
.. |buildstatus| image:: https://travis-ci.org/rocky/python-uncompyle6.svg
:target: https://travis-ci.org/rocky/python-uncompyle6
.. |packagestatus| image:: https://repology.org/badge/vertical-allrepos/python:uncompyle6.svg
:target: https://repology.org/project/python:uncompyle6/versions
.. _PJOrion: http://www.koreanrandom.com/forum/topic/15280-pjorion-%D1%80%D0%B5%D0%B4%D0%B0%D0%BA%D1%82%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D0%B5-%D0%BA%D0%BE%D0%BC%D0%BF%D0%B8%D0%BB%D1%8F%D1%86%D0%B8%D1%8F-%D0%B4%D0%B5%D0%BA%D0%BE%D0%BC%D0%BF%D0%B8%D0%BB%D1%8F%D1%86%D0%B8%D1%8F-%D0%BE%D0%B1%D1%84
.. _pydecipher: https://github.com/mitre/pydecipher
.. _Deobfuscator: https://github.com/extremecoders-re/PjOrion-Deobfuscator
.. _Py2EXE: https://en.wikipedia.org/wiki/Py2exe
.. |Supported Python Versions| image:: https://img.shields.io/pypi/pyversions/uncompyle6.svg
.. |Latest Version| image:: https://badge.fury.io/py/uncompyle6.svg
:target: https://badge.fury.io/py/uncompyle6
.. |Pypi Installs| image:: https://pepy.tech/badge/uncompyle6/month
Platform: UNKNOWN
Classifier: Development Status :: 5 - Production/Stable
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: GNU General Public License v3 (GPLv3)
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python
Classifier: Programming Language :: Python :: 2
Classifier: Programming Language :: Python :: 2.4
Classifier: Programming Language :: Python :: 2.5
Classifier: Programming Language :: Python :: 2.6
Classifier: Programming Language :: Python :: 2.7
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.0
Classifier: Programming Language :: Python :: 3.1
Classifier: Programming Language :: Python :: 3.2
Classifier: Programming Language :: Python :: 3.3
Classifier: Programming Language :: Python :: 3.4
Classifier: Programming Language :: Python :: 3.5
Classifier: Programming Language :: Python :: 3.6
Classifier: Programming Language :: Python :: 3.7
Classifier: Programming Language :: Python :: 3.8
Classifier: Programming Language :: Python :: 3.9
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: Implementation :: PyPy
Classifier: Topic :: Software Development :: Debuggers
Classifier: Topic :: Software Development :: Libraries :: Python Modules

View File

@@ -2,12 +2,16 @@
|packagestatus|
.. contents::
uncompyle6
==========
A native Python cross-version decompiler and fragment decompiler.
The successor to decompyle, uncompyle, and uncompyle2.
I gave a talk on this at `BlackHat Asia 2024 <https://youtu.be/H-7ZNrpsV50?si=nOaixgYHr7RbILVS>`_.
Introduction
------------
@@ -39,7 +43,7 @@ although compatible with the original intention, is yet a little bit
different. See this_ for more information.
Python fragment deparsing given an instruction offset is useful in
showing stack traces and can be encorporated into any program that
showing stack traces and can be incorporated into any program that
wants to show a location in more detail than just a line number at
runtime. This code can be also used when source-code information does
not exist and there is just bytecode. Again, my debuggers make use of
@@ -68,32 +72,51 @@ 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
------------
The code here can be run on Python versions 2.6 or later, PyPy 3-2.4
and later. Python versions 2.4-2.7 are supported in the python-2.4
branch. The bytecode files it can read have been tested on Python
The code in the git repository can be run from Python 2.4 to the
latest Python version, with the exception of Python 3.0 through
3.2. Volunteers are welcome to address these deficiencies if there a
desire to do so.
The way it does this though is by segregating consecutive Python versions into
git branches:
master
Python 3.6 and up (uses type annotations)
python-3.3-to-3.5
Python 3.3 through 3.5 (Generic Python 3)
python-2.4
Python 2.4 through 2.7 (Generic Python 2)
PyPy 3-2.4 and later works as well.
The bytecode files it can read have been tested on Python
bytecodes from versions 1.4, 2.1-2.7, and 3.0-3.8 and later PyPy
versions.
Installation
------------
This uses setup.py, so it follows the standard Python routine:
You can install from PyPI using the name ``uncompyle6``::
::
pip install uncompyle6
To install from source code, this project uses setup.py, so it follows the standard Python routine::
$ pip install -e . # set up to run from source tree
# Or if you want to install instead
or::
$ python setup.py install # may need sudo
A GNU makefile is also provided so :code:`make install` (possibly as root or
A GNU Makefile is also provided so :code:`make install` (possibly as root or
sudo) will do the steps above.
Running Tests
@@ -130,7 +153,7 @@ Verification
In older versions of Python it was possible to verify bytecode by
decompiling bytecode, and then compiling using the Python interpreter
for that bytecode version. Having done this the bytecode produced
for that bytecode version. Having done this, the bytecode produced
could be compared with the original bytecode. However as Python's code
generation got better, this no longer was feasible.
@@ -140,11 +163,11 @@ Python syntax changes, you should use this option if the bytecode is
the right bytecode for the Python interpreter that will be checking
the syntax.
You can also cross compare the results with either another version of
`uncompyle6` since there are are sometimes regressions in decompiling
You can also cross compare the results with another version of
*uncompyle6* since there are sometimes regressions in decompiling
specific bytecode as the overall quality improves.
For Python 3.7 and above, the code in decompyle3_ is generally
For Python 3.7 and 3.8, the code in decompyle3_ is generally
better.
Or try specific another python decompiler like uncompyle2_, unpyc37_,
@@ -172,17 +195,13 @@ 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
In the Python 3 series, Python support is strongest around 3.4 or
3.3 and drops off as you move further away from those versions. Python
3.0 is weird in that it in some ways resembles 2.6 more than it does
3.1 or 2.7. Python 3.6 changes things drastically by using word codes
@@ -195,7 +214,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
@@ -211,40 +230,78 @@ however that the magic of a released version is usually the same as
the *last* candidate version prior to release.
There are also customized Python interpreters, notably Dropbox,
which use their own magic and encrypt bytcode. With the exception of
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; pydecipher_ might help with that.
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. `Pydeinstaller <https://github.com/charles-dyfis-net/pydeinstaller>`_ may help with unpacking Pyinstaller bundlers.
There is lots to do, so please dig in and help.
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.
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*. Any volunteers?
You may run across a bug, that you want to report. Please do so after
reading `How to report a bug
<https://github.com/rocky/python-uncompyle6/blob/master/HOW-TO-REPORT-A-BUG.md>`_ and
follow the `instructions when opening an issue <https://github.com/rocky/python-uncompyle6/issues/new?assignees=&labels=&template=bug-report.md>`_.
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. In
rare situtations, I can do a hand decompilation of bytecode for a fee.
However this is expansive, usually beyond what most people are willing
to spend.
See Also
--------
* https://github.com/rocky/python-decompile3 : Much smaller and more modern code, focusing on 3.7+. Changes in that will get migrated back ehre.
* https://rocky.github.io/blackhat-asia-2024-additional/all-notes-print.html : How to Read and Write a High-Level Bytecode Decompiler: ``uncompyle6`` ``decompyle3`` -- BlackHat 2024 Asia (`video <https://www.youtube.com/watch?v=NA77SFncppE>`_). A big thanks to the Organizers and Reviewers for letting me speak. This kind of thing encourages me to work on projects like this.
* https://github.com/rocky/python-decompile3 : Much smaller and more modern code, focusing on 3.7 and 3.8. Changes in that will get migrated back here.
* https://code.google.com/archive/p/unpyc3/ : supports Python 3.2 only. The above projects use a different decompiling technique than what is used here. Currently unmaintained.
* https://github.com/figment/unpyc3/ : fork of above, but supports Python 3.3 only. Includes some fixes like supporting function annotations. Currently unmaintained.
* https://github.com/wibiti/uncompyle2 : supports Python 2.7 only, but does that fairly well. There are situations where :code:`uncompyle6` results are incorrect while :code:`uncompyle2` results are not, but more often uncompyle6 is correct when uncompyle2 is not. Because :code:`uncompyle6` adheres to accuracy over idiomatic Python, :code:`uncompyle2` can produce more natural-looking code when it is correct. Currently :code:`uncompyle2` is lightly maintained. See its issue `tracker <https://github.com/wibiti/uncompyle2/issues>`_ for more details
* https://github.com/wibiti/uncompyle2 : supports Python 2.7 only, but does that fairly well. There are situations where :code:`uncompyle6` results are incorrect while :code:`uncompyle2` results are not, but more often uncompyle6 is correct when uncompyle2 is not. Because :code:`uncompyle6` adheres to accuracy over idiomatic Python, :code:`uncompyle2` can produce more natural-looking code when it is correct. Currently :code:`uncompyle2` is lightly maintained. See its issue `tracker <https://github.com/wibiti/uncompyle2/issues>`_ for more details.
* `How to report a bug <https://github.com/rocky/python-uncompyle6/blob/master/HOW-TO-REPORT-A-BUG.md>`_
* The HISTORY_ file.
* https://github.com/rocky/python-xdis : Cross Python version disassembler
* https://github.com/rocky/python-xasm : Cross Python version assembler
* https://github.com/rocky/python-uncompyle6/wiki : Wiki Documents which describe the code and aspects of it in more detail
* 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.
* https://github.com/zrax/pycdc : The README for this C++ code says it aims to support all versions of Python. You can aim your slign shot for the moon too, but I doubt you are going to hit it. This code 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.
.. _trepan: https://pypi.python.org/pypi/trepan2g
.. _compiler: https://pypi.python.org/pypi/spark_parser
.. _Cython: https://en.wikipedia.org/wiki/Cython
.. _trepan: https://pypi.python.org/pypi/trepan3k
.. _compiler: https://github.com/rocky/python-uncompyle6/wiki/How-does-this-code-work%3F
.. _HISTORY: https://github.com/rocky/python-uncompyle6/blob/master/HISTORY.md
.. _report_bug: https://github.com/rocky/python-uncompyle6/blob/master/HOW-TO-REPORT-A-BUG.md
.. _debuggers: https://pypi.python.org/pypi/trepan3k
.. _remake: https://bashdb.sf.net/remake
.. _pycdc: https://github.com/zrax/pycdc
@@ -252,11 +309,12 @@ See Also
.. _uncompyle2: https://github.com/wibiti/uncompyle2
.. _unpyc37: https://github.com/andrew-tavera/unpyc37
.. _this: https://github.com/rocky/python-uncompyle6/wiki/Deparsing-technology-and-its-use-in-exact-location-reporting
.. |buildstatus| image:: https://travis-ci.org/rocky/python-uncompyle6.svg
:target: https://travis-ci.org/rocky/python-uncompyle6
.. |buildstatus| image:: https://circleci.com/gh/rocky/python-uncompyle6.svg?style=svg
:target: https://app.circleci.com/pipelines/github/rocky/python-uncompyle6
.. |packagestatus| image:: https://repology.org/badge/vertical-allrepos/python:uncompyle6.svg
:target: https://repology.org/project/python:uncompyle6/versions
.. _PJOrion: http://www.koreanrandom.com/forum/topic/15280-pjorion-%D1%80%D0%B5%D0%B4%D0%B0%D0%BA%D1%82%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D0%B5-%D0%BA%D0%BE%D0%BC%D0%BF%D0%B8%D0%BB%D1%8F%D1%86%D0%B8%D1%8F-%D0%B4%D0%B5%D0%BA%D0%BE%D0%BC%D0%BF%D0%B8%D0%BB%D1%8F%D1%86%D0%B8%D1%8F-%D0%BE%D0%B1%D1%84
.. _pydecipher: https://github.com/mitre/pydecipher
.. _Deobfuscator: https://github.com/extremecoders-re/PjOrion-Deobfuscator
.. _Py2EXE: https://en.wikipedia.org/wiki/Py2exe
.. |Supported Python Versions| image:: https://img.shields.io/pypi/pyversions/uncompyle6.svg

View File

@@ -1,4 +1,4 @@
# Copyright (C) 2018, 2020 Rocky Bernstein <rocky@gnu.org>
# Copyright (C) 2018, 2020-2021 2024 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
@@ -21,66 +21,89 @@
# less elegant than having it here with reduced code, albeit there
# still is some room for improvement.
# Python-version | package | last-version |
# -----------------------------------------
# 2.5 | pip | 1.1 |
# 2.6 | pip | 1.5.6 |
# 2.7 | pip | 19.2.3 |
# 2.7 | pip | 1.2.1 |
# 3.1 | pip | 1.5.6 |
# 3.2 | pip | 7.1.2 |
# 3.3 | pip | 10.0.1 |
# 3.4 | pip | 19.1.1 |
import os.path as osp
# Things that change more often go here.
copyright = """
Copyright (C) 2015-2020 Rocky Bernstein <rb@dustyfeet.com>.
copyright = """
Copyright (C) 2015-2021, 2024 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 :: 3.11",
"Programming Language :: Python :: 3.12",
"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.5.1, < 4.6.0"]
]
}
ftp_url = None
install_requires = ["click", "spark-parser >= 1.8.9, < 1.9.2", "xdis >= 6.1.1, < 6.2.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)
filename = osp.normcase(osp.dirname(osp.abspath(__file__)))
return osp.realpath(filename)
srcdir = get_srcdir()
def read(*rnames):
return open(os.path.join(srcdir, *rnames)).read()
return open(osp.join(srcdir, *rnames)).read()
# Get info from files; set: long_description and VERSION
long_description = ( read("README.rst") + "\n" )
long_description = read("README.rst") + "\n"
exec(read("uncompyle6/version.py"))

1
admin-tools/.gitignore vendored Normal file
View File

@@ -0,0 +1 @@
/.python-version

View File

@@ -1,4 +1,6 @@
#!/bin/bash
# Run tests over all Python versions in branch python-2.4-2.7
set -e
function finish {
cd $owd
}
@@ -6,11 +8,13 @@ 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
exit $?
rc=$?
finish
exit $rc
fi
cd ..
@@ -21,7 +25,10 @@ for version in $PYVERSIONS; do
fi
make clean && python setup.py develop
if ! make check ; then
finish
rc=$?
exit $?
fi
echo === $version ===
done
finish

View File

@@ -0,0 +1,31 @@
#!/bin/bash
# Run tests over all Python versions in branch python-3.0-3.2
set -e
function finish {
cd $owd
}
owd=$(pwd)
trap finish EXIT
cd $(dirname ${BASH_SOURCE[0]})
if ! source ./pyenv-3.0-3.2-versions ; then
exit $?
fi
if ! source ./setup-python-3.0.sh ; then
exit $?
fi
cd ..
for version in $PYVERSIONS; do
echo --- $version ---
if ! pyenv local $version ; then
exit $?
fi
make clean && python setup.py develop
if ! make check ; then
exit $?
fi
echo === $version ===
done
finish

View File

@@ -0,0 +1,30 @@
#!/bin/bash
# Run tests over all Python versions in branch python-3.3-3.5
set -e
function finish {
cd $owd
}
owd=$(pwd)
trap finish EXIT
cd $(dirname ${BASH_SOURCE[0]})
if ! source ./pyenv-3.3-3.5-versions ; then
exit $?
fi
if ! source ./setup-python-3.3.sh ; then
exit $?
fi
cd ..
for version in $PYVERSIONS; do
echo --- $version ---
if ! pyenv local $version ; then
exit $?
fi
make clean && python setup.py develop
if ! make check ; then
exit $?
fi
echo === $version ===
done
finish

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

@@ -0,0 +1,21 @@
# Common checkout routine
export PATH=$HOME/.pyenv/bin/pyenv:$PATH
bs=${BASH_SOURCE[0]}
mydir=$(dirname $bs)
fulldir=$(readlink -f $mydir)
function setup_version {
local repo=$1
version=$2
echo Running setup $version on $repo ...
(cd ../$repo && . ./admin-tools/setup-${version}.sh)
return $?
}
function checkout_finish {
branch=$1
cd $uncompyle6_owd
git checkout $branch && pyenv local $PYTHON_VERSION && git pull
rc=$?
return $rc
}

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,39 +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.2
$ pyenv local 3.8.5
$ twine check dist/uncompyle6-$VERSION*
$ git tag release-python-2.4-$VERSION
$ twine check dist/uncompyle6-$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

@@ -3,13 +3,13 @@ PACKAGE=uncompyle6
# FIXME put some of the below in a common routine
function finish {
cd $owd
cd $make_dist_uncompyle6_owd
}
owd=$(pwd)
make_dist_uncompyle6_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,9 +18,14 @@ fi
cd ..
source $PACKAGE/version.py
echo $VERSION
echo $__version__
for pyversion in $PYVERSIONS; do
echo --- $pyversion ---
if [[ ${pyversion:0:4} == "pypy" ]] ; then
echo "$pyversion - PyPy does not get special packaging"
continue
fi
if ! pyenv local $pyversion ; then
exit $?
fi
@@ -29,11 +34,16 @@ 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
finish

View File

@@ -0,0 +1,49 @@
#!/bin/bash
PACKAGE=uncompyle6
# FIXME put some of the below in a common routine
function finish {
cd $uncompyle6_30_make_dist_owd
}
cd $(dirname ${BASH_SOURCE[0]})
uncompyle6_30_make_dist_owd=$(pwd)
trap finish EXIT
if ! source ./pyenv-3.0-3.2-versions ; then
exit $?
fi
if ! source ./setup-python-3.0.sh ; then
exit $?
fi
cd ..
source $PACKAGE/version.py
echo $__version__
for pyversion in $PYVERSIONS; do
echo --- $pyversion ---
if [[ ${pyversion:0:4} == "pypy" ]] ; then
echo "$pyversion - PyPy does not get special packaging"
continue
fi
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
echo === $pyversion ===
done
python ./setup.py sdist
tarball=dist/${PACKAGE}-${__version__}.tar.gz
if [[ -f $tarball ]]; then
mv -v $tarball dist/${PACKAGE}_31-${__version__}.tar.gz
fi
finish

View File

@@ -0,0 +1,49 @@
#!/bin/bash
PACKAGE=uncompyle6
# FIXME put some of the below in a common routine
function finish {
cd $uncompyle6_33_make_owd
}
cd $(dirname ${BASH_SOURCE[0]})
uncompyle6_33_make_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
echo --- $pyversion ---
if [[ ${pyversion:0:4} == "pypy" ]] ; then
echo "$pyversion - PyPy does not get special packaging"
continue
fi
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
echo === $pyversion ===
done
python ./setup.py sdist
tarball=dist/${PACKAGE}-${__version__}.tar.gz
if [[ -f $tarball ]]; then
mv -v $tarball dist/${PACKAGE}_31-${__version__}.tar.gz
fi
finish

View File

@@ -3,14 +3,14 @@ PACKAGE=uncompyle6
# FIXME put some of the below in a common routine
function finish {
cd $owd
cd $make_uncompyle6_newest_owd
}
cd $(dirname ${BASH_SOURCE[0]})
owd=$(pwd)
make_uncompyle6_newest_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,9 +19,14 @@ fi
cd ..
source $PACKAGE/version.py
echo $VERSION
echo $__version__
for pyversion in $PYVERSIONS; do
echo --- $pyversion ---
if [[ ${pyversion:0:4} == "pypy" ]] ; then
echo "$pyversion - PyPy does not get special packaging"
continue
fi
if ! pyenv local $pyversion ; then
exit $?
fi
@@ -32,7 +37,8 @@ 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
finish

7
admin-tools/merge-for-2.4.sh Executable file
View File

@@ -0,0 +1,7 @@
#/bin/bash
uncompyle6_merge_24_owd=$(pwd)
cd $(dirname ${BASH_SOURCE[0]})
if . ./setup-python-2.4.sh; then
git merge python-3.0-to-3.2
fi
cd $uncompyle6_merge_24_owd

7
admin-tools/merge-for-3.0.sh Executable file
View File

@@ -0,0 +1,7 @@
#/bin/bash
uncompyle6_merge_30_owd=$(pwd)
cd $(dirname ${BASH_SOURCE[0]})
if . ./setup-python-3.0.sh; then
git merge python-3.3-to-3.5
fi
cd $uncompyle6_merge_30_owd

7
admin-tools/merge-for-3.3.sh Executable file
View File

@@ -0,0 +1,7 @@
#/bin/bash
uncompyle6_merge_33_owd=$(pwd)
cd $(dirname ${BASH_SOURCE[0]})
if . ./setup-python-3.3.sh; then
git merge python-3.6-to-3.10
fi
cd $uncompyle6_merge_33_owd

7
admin-tools/merge-for-3.6.sh Executable file
View File

@@ -0,0 +1,7 @@
#/bin/bash
uncompyle6_merge_36_owd=$(pwd)
cd $(dirname ${BASH_SOURCE[0]})
if . ./setup-python-3.6.sh; then
git merge master
fi
cd $uncompyle6_merge_36_owd

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 2.6.9'
export PYVERSIONS='3.0.1 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.5.10 3.3.7 3.4.10'

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.6.15 pypy3.6-7.3.1 3.7.16 pypy3.7-7.3.9 pypy3.8-7.3.10 pyston-2.3.5 3.8.18'

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.2'
export PYVERSIONS='3.7.13 pyston-2.3.3 3.8.13'

View File

@@ -1,23 +1,20 @@
#!/bin/bash
PYTHON_VERSION=3.7.7
# FIXME put some of the below in a common routine
function finish {
cd $owd
}
export PATH=$HOME/.pyenv/bin/pyenv:$PATH
owd=$(pwd)
# Check out master branch and dependent development master branches
bs=${BASH_SOURCE[0]}
if [[ $0 == $bs ]] ; then
echo "This script should be *sourced* rather than run directly through bash"
exit 1
fi
PYTHON_VERSION=3.12
uncompyle6_owd=$(pwd)
mydir=$(dirname $bs)
fulldir=$(readlink -f $mydir)
cd $mydir
. ./checkout_common.sh
cd $fulldir/..
(cd ../python-spark && git checkout master && pyenv local $PYTHON_VERSION) && git pull && \
(cd ../python-xdis && git checkout master && pyenv local $PYTHON_VERSION) && git pull && \
git checkout master && pyenv local $PYTHON_VERSION && git pull
cd $owd
rm -v */.python-version || true
(cd $fulldir/.. && \
setup_version python-spark master && \
setup_version python-xdis master )
checkout_finish master

View File

@@ -1,17 +1,23 @@
#!/bin/bash
PYTHON_VERSION=2.4.6
# Check out python-2.4-to-2.7 and dependent development branches.
owd=$(pwd)
bs=${BASH_SOURCE[0]}
if [[ $0 == $bs ]] ; then
echo "This script should be *sourced* rather than run directly through bash"
exit 1
fi
PYTHON_VERSION=2.4
uncompyle6_owd=$(pwd)
mydir=$(dirname $bs)
fulldir=$(readlink -f $mydir)
cd $fulldir/..
(cd ../python-spark && git checkout python-2.4 && pyenv local $PYTHON_VERSION) && git pull && \
(cd ../python-xdis && git checkout python-2.4 && pyenv local $PYTHON_VERSION) && git pull && \
git checkout python-2.4 && pyenv local $PYTHON_VERSION && git pull
cd $owd
rm -v */.python-version || true
cd $mydir
. ./checkout_common.sh
(cd $fulldir/.. && \
setup_version python-spark python-2.4 && \
setup_version python-xdis python-2.4)
checkout_finish python-2.4-to-2.7

View File

@@ -0,0 +1,20 @@
#!/bin/bash
# Check out python-3.0-to-3.2 and dependent development branches.
bs=${BASH_SOURCE[0]}
if [[ $0 == $bs ]] ; then
echo "This script should be *sourced* rather than run directly through bash"
exit 1
fi
PYTHON_VERSION=3.0
uncompyle6_owd=$(pwd)
mydir=$(dirname $bs)
fulldir=$(readlink -f $mydir)
cd $mydir
. ./checkout_common.sh
(cd $fulldir/.. && \
setup_version python-spark python-3.0 && \
setup_version python-xdis python-3.0)
checkout_finish python-3.0-to-3.2

21
admin-tools/setup-python-3.3.sh Executable file
View File

@@ -0,0 +1,21 @@
#!/bin/bash
# Check out python-3.3-to-3.5 and dependent development branches.
bs=${BASH_SOURCE[0]}
if [[ $0 == $bs ]] ; then
echo "This script should be *sourced* rather than run directly through bash"
exit 1
fi
PYTHON_VERSION=3.3
uncompyle6_owd=$(pwd)
mydir=$(dirname $bs)
cd $mydir
fulldir=$(readlink -f $mydir)
. ./checkout_common.sh
cd $fulldir/..
(cd $fulldir/.. && \
setup_version python-spark python-3.3 && \
setup_version python-xdis python-3.3 )
checkout_finish python-3.3-to-3.5

21
admin-tools/setup-python-3.6.sh Executable file
View File

@@ -0,0 +1,21 @@
#!/bin/bash
# Check out python-3.6-to-3.10 and dependent development branches.
bs=${BASH_SOURCE[0]}
if [[ $0 == $bs ]] ; then
echo "This script should be *sourced* rather than run directly through bash"
exit 1
fi
PYTHON_VERSION=3.6
uncompyle6_owd=$(pwd)
mydir=$(dirname $bs)
cd $mydir
fulldir=$(readlink -f $mydir)
. ./checkout_common.sh
cd $fulldir/..
(cd $fulldir/.. && \
setup_version python-spark python-3.6 && \
setup_version python-xdis python-3.6 )
checkout_finish python-3.6-to-3.10

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
#

65
pyproject.toml Normal file
View File

@@ -0,0 +1,65 @@
[build-system]
requires = [
"setuptools",
# "setuptools>=59.6.0", # for 3.6
]
build-backend = "setuptools.build_meta"
[project]
authors = [
{name = "Rocky Bernstein", email = "rb@dustyfeet.com"},
]
name = "uncompyle6"
description = "Python cross-version byte-code library and disassembler"
dependencies = [
"click",
"spark-parser >= 1.8.9, < 1.9.2",
"xdis >= 6.1.0, < 6.2.0",
]
readme = "README.rst"
license = {text = "GPL"}
keywords = ["Python bytecode", "bytecode", "disassembler"]
classifiers = [
"Development Status :: 5 - Production/Stable",
"Intended Audience :: Developers",
"License :: OSI Approved :: MIT License",
"Programming Language :: Python",
"Topic :: Software Development :: Libraries :: Python Modules",
"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",
"Programming Language :: Python :: 3.9",
"Programming Language :: Python :: 3.10",
"Programming Language :: Python :: 3.11",
"Programming Language :: Python :: 3.12",
]
dynamic = ["version"]
[project.urls]
Homepage = "https://github.com/rocky/python-uncompyle6"
Downloads = "https://github.com/rocky/python-uncompyle6/releases"
[project.optional-dependencies]
dev = [
"pre-commit",
"pytest",
]
[project.scripts]
uncompyle6 = "uncompyle6.bin.uncompile:main_bin"
uncompyle6-tokenize = "uncompyle6.bin.pydisassemble:main"
[tool.setuptools.dynamic]
version = {attr = "uncompyle6.version.__version__"}

View File

@@ -7,5 +7,5 @@ PYTHON ?= python
test check pytest:
@PYTHON_VERSION=`$(PYTHON) -V 2>&1 | cut -d ' ' -f 2 | cut -d'.' -f1,2`; \
if [[ $$PYTHON_VERSION > 3.2 ]] || [[ $$PYTHON_VERSION == 2.7 ]] || [[ $$PYTHON_VERSION == 2.6 ]]; then \
py.test; \
$(PYTHON) -m pytest .; \
fi

View File

@@ -1,10 +1,10 @@
import pytest
# uncompyle6
from uncompyle6 import PYTHON_VERSION
from xdis.version_info import PYTHON_VERSION_TRIPLE, IS_PYPY
from validate import validate_uncompyle
@pytest.mark.skipif(PYTHON_VERSION < 3.6, reason='need at least python 3.6')
@pytest.mark.skipif(PYTHON_VERSION_TRIPLE < (3, 6) or IS_PYPY, reason="need at least Python 3.6 and not PyPY")
@pytest.mark.parametrize('text', (
"{0.: 'a', -1: 'b'}", # BUILD_MAP
"{'a':'b'}", # BUILD_MAP

View File

@@ -1,6 +1,5 @@
import pytest
from uncompyle6.semantics.fragments import code_deparse as deparse, deparsed_find
from uncompyle6 import PYTHON_VERSION, PYTHON3
from uncompyle6.semantics.fragments import code_deparse as deparse
from xdis.version_info import PYTHON_VERSION_TRIPLE
def map_stmts(x, y):
x = []
@@ -30,20 +29,18 @@ def list_comp():
[y for y in range(3)]
def get_parsed_for_fn(fn):
code = fn.__code__ if PYTHON3 else fn.func_code
return deparse(code, version=PYTHON_VERSION)
code = fn.__code__
return deparse(code, version=PYTHON_VERSION_TRIPLE)
def check_expect(expect, parsed, fn_name):
debug = False
i = 2
max_expect = len(expect)
code = get_parsed_for_fn(fn_name)
for name, offset in sorted(parsed.offsets.keys()):
assert i+1 <= max_expect, (
"%s: ran out if items in testing node" % fn_name)
nodeInfo = parsed.offsets[name, offset]
node = nodeInfo.node
nodeInfo2 = deparsed_find((name, offset), parsed, code)
extractInfo = parsed.extract_node_info(node)
assert expect[i] == extractInfo.selectedLine, \
@@ -319,5 +316,3 @@ for i in range(2): ...
.
""".split("\n")
parsed = get_parsed_for_fn(for_range_stmt)
if not PYTHON3:
check_expect(expect, parsed, 'range_stmt')

View File

@@ -1,7 +1,7 @@
import os.path
import pytest
from uncompyle6.disas import disassemble_file
from uncompyle6.code_fns import disassemble_file
def get_srcdir():
filename = os.path.normcase(os.path.dirname(__file__))

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,13 +21,13 @@ def bug_loop(disassemble, tb=None):
def test_if_in_for():
code = bug.__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)
## FIXME: the data below is wrong.
## we get different results currenty as well.
## we get different results currently as well.
## We need to probably fix both the code
## and the test below
# assert {15: [3], 69: [66], 63: [18]} == fjt
@@ -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, IS_PYPY
def test_grammar():
@@ -16,71 +16,71 @@ 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")
expect_lhs.add("async_with_stmt")
unused_rhs = set(["list", "mkfunc", "mklambda", "unpack"])
unused_rhs = set(["list", "mkfunc", "lambda_body", "unpack"])
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")
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")
if PYTHON3:
expect_lhs.add("load_genexpr")
expect_lhs.add("load_genexpr")
unused_rhs = unused_rhs.union(
set(
"""
except_pop_except generator_exp
""".split()
)
unused_rhs = unused_rhs.union(
set(
"""
except_pop_except generator_exp
""".split()
)
if PYTHON_VERSION >= 3.0:
if PYTHON_VERSION < 3.7:
expect_lhs.add("annotate_arg")
expect_lhs.add("annotate_tuple")
unused_rhs.add("mkfunc_annotate")
)
if PYTHON_VERSION_TRIPLE < (3, 7):
expect_lhs.add("annotate_arg")
expect_lhs.add("annotate_tuple")
unused_rhs.add("mkfunc_annotate")
unused_rhs.add("dict_comp")
unused_rhs.add("classdefdeco1")
unused_rhs.add("tryelsestmtl")
if PYTHON_VERSION >= 3.5:
expect_right_recursive.add(
(("l_stmts", ("lastl_stmt", "come_froms", "l_stmts")))
)
pass
pass
unused_rhs.add("dict_comp")
unused_rhs.add("classdefdeco1")
unused_rhs.add("tryelsestmtl")
if PYTHON_VERSION_TRIPLE >= (3, 5):
expect_right_recursive.add(
(("l_stmts", ("lastl_stmt", "come_froms", "l_stmts")))
)
pass
else:
expect_lhs.add("kwarg")
pass
if PYTHON_VERSION_TRIPLE >= (3, 7):
expect_lhs.add("set_for")
unused_rhs.add("set_iter")
pass
pass
# FIXME
if PYTHON_VERSION < 3.8:
if PYTHON_VERSION_TRIPLE < (3, 8):
assert expect_lhs == set(lhs)
assert unused_rhs == set(rhs)
@@ -103,7 +103,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
@@ -116,12 +116,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)
@@ -132,7 +133,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,19 +1,13 @@
import sys
from uncompyle6 import PYTHON3
from uncompyle6.scanner import get_scanner
from uncompyle6.semantics.consts import (
escape, NONE,
# RETURN_NONE, PASS, RETURN_LOCALS
)
if PYTHON3:
from io import StringIO
def iteritems(d):
return d.items()
else:
from StringIO import StringIO
def iteritems(d):
return d.iteritems()
from io import StringIO
def iteritems(d):
return d.items()
from uncompyle6.semantics.pysource import (SourceWalker, deparse_code2str)

View File

@@ -1,22 +1,24 @@
import pytest
from uncompyle6 import PYTHON_VERSION, code_deparse
pytestmark = pytest.mark.skip(PYTHON_VERSION < 2.7,
reason="need at least Python 2.7")
from uncompyle6 import code_deparse
from xdis.version_info import PYTHON_VERSION_TRIPLE
if PYTHON_VERSION > 2.6:
def test_single_mode():
single_expressions = (
'i = 1',
'i and (j or k)',
'i += 1',
'i = j % 4',
'i = {}',
'i = []',
'for i in range(10):\n i\n',
'for i in range(10):\n for j in range(10):\n i + j\n',
'try:\n i\nexcept Exception:\n j\nelse:\n k\n'
)
pytest.mark.skip(PYTHON_VERSION_TRIPLE < (2, 7), reason="need Python < 2.7")
for expr in single_expressions:
code = compile(expr + '\n', '<string>', 'single')
assert code_deparse(code, compile_mode='single').text == expr + '\n'
def test_single_mode():
single_expressions = (
"i = 1",
"i and (j or k)",
"i += 1",
"i = j % 4",
"i = {}",
"i = []",
"for i in range(10):\n i\n",
"for i in range(10):\n for j in range(10):\n i + j\n",
# 'try:\n i\nexcept Exception:\n j\nelse:\n k\n'
)
for expr in single_expressions:
code = compile(expr + "\n", "<string>", "single")
got = code_deparse(code, compile_mode="single").text
assert got == expr + "\n"

View File

@@ -9,22 +9,16 @@ 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, 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.bytecode import Bytecode
from xdis.main import get_opcode
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
if PYTHON3:
from io import StringIO
else:
from StringIO import StringIO
def _dis_to_text(co):
return Bytecode(co).dis()
@@ -73,7 +67,7 @@ def are_instructions_equal(i1, i2):
Determine if two instructions are approximately equal,
ignoring certain fields which we allow to differ, namely:
* code objects are ignore (should probaby be checked) due to address
* code objects are ignore (should probably be checked) due to address
* line numbers
:param i1: left instruction to compare
@@ -128,7 +122,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

@@ -2,3 +2,8 @@
hypothesis==2.0.0
pytest
-e .
Click~=7.0
xdis>=6.0.4
configobj~=5.0.6
setuptools

71
setup-pretoml.py Normal file
View File

@@ -0,0 +1,71 @@
#!/usr/bin/env python
import sys
import setuptools
"""Setup script for the 'uncompyle6' distribution."""
SYS_VERSION = sys.version_info[0:2]
if SYS_VERSION < (3, 6):
mess = "Python Release 3.6 .. 3.12 are supported in this code branch."
if (2, 4) <= SYS_VERSION <= (2, 7):
mess += (
"\nFor your Python, version %s, use the python-2.4 code/branch."
% sys.version[0:3]
)
if SYS_VERSION >= (3, 6):
mess += (
"\nFor your Python, version %s, use the master code/branch."
% sys.version[0:3]
)
if (3, 0) >= SYS_VERSION < (3, 3):
mess += (
"\nFor your Python, version %s, use the python-3.0-to-3.2 code/branch."
% sys.version[0:3]
)
if (3, 3) >= SYS_VERSION < (3, 6):
mess += (
"\nFor your Python, version %s, use the python-3.3-to-3.5 code/branch."
% sys.version[0:3]
)
elif SYS_VERSION < (2, 4):
mess += (
"\nThis package is not supported for Python version %s." % sys.version[0:3]
)
print(mess)
raise Exception(mess)
from __pkginfo__ import (
__version__,
author,
author_email,
classifiers,
entry_points,
install_requires,
license,
long_description,
modname,
py_modules,
short_desc,
web,
zip_safe,
)
setuptools.setup(
author=author,
author_email=author_email,
classifiers=classifiers,
description=short_desc,
entry_points=entry_points,
install_requires=install_requires,
license=license,
long_description=long_description,
long_description_content_type="text/x-rst",
name=modname,
packages=setuptools.find_packages(),
py_modules=py_modules,
test_suite="nose.collector",
url=web,
version=__version__,
zip_safe=zip_safe,
)

View File

@@ -1,11 +1,58 @@
[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 = no
[egg_info]
tag_build =
tag_date = 0
[metadata]
description_file = README.rst
licences_files = COPYING
[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

@@ -1,43 +1,6 @@
#!/usr/bin/env python
import sys
"""Setup script for the 'uncompyle6' distribution."""
SYS_VERSION = sys.version_info[0:2]
if not ((2, 6) <= SYS_VERSION <= (3, 9)):
mess = "Python Release 2.6 .. 3.9 are supported in this code branch."
if ((2, 4) <= SYS_VERSION <= (2, 7)):
mess += ("\nFor your Python, version %s, use the python-2.4 code/branch." %
sys.version[0:3])
elif SYS_VERSION < (2, 4):
mess += ("\nThis package is not supported for Python version %s."
% sys.version[0:3])
print(mess)
raise Exception(mess)
from setuptools import setup
from __pkginfo__ import \
author, author_email, install_requires, \
license, long_description, classifiers, \
entry_points, modname, py_modules, \
short_desc, VERSION, web, \
zip_safe
from setuptools import setup, find_packages
setup(
author = author,
author_email = author_email,
classifiers = classifiers,
description = short_desc,
entry_points = entry_points,
install_requires = install_requires,
license = license,
long_description = long_description,
long_description_content_type = "text/x-rst",
name = modname,
packages = find_packages(),
py_modules = py_modules,
test_suite = 'nose.collector',
url = web,
tests_require = ['nose>=1.0'],
version = VERSION,
zip_safe = zip_safe)
setup(packages=["uncompyle6"])

5
test/.gitignore vendored
View File

@@ -1,3 +1,8 @@
/.coverage
/.python-version
/nohup.out
/pycdc
/test_pycdc_tests.sh
/test_uncompyle2.py
/test_unpy33.py
/test_unpy37.py

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:
@@ -72,14 +72,23 @@ check-3.7: check-bytecode
$(PYTHON) test_pythonlib.py --bytecode-3.7-run --verify-run
$(PYTHON) test_pythonlib.py --bytecode-3.7 --syntax-verify $(COMPILE)
check-pypy37: check-bytecode
$(PYTHON) test_pythonlib.py --bytecode-pypy37 --verify-run
#: Run working tests from Python 3.8
check-3.8: 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:
#: this is called when running under pypy3.5-5.8.0, pypy2-5.6.0, pypy3.6-7.3.0 or pypy3.8-7.3.7
5.8 5.6 7.3:
#: Check deparsing only, but from a different Python version
check-disasm:
@@ -106,7 +115,7 @@ check-bytecode-2:
# FIXME: Until we shaked out problems with xdis...
check-bytecode-3:
$(PYTHON) test_pythonlib.py \
--bytecode-3.4 --bytecode-3.5 --bytecode-3.6 \
--bytecode-3.3 --bytecode-3.4 --bytecode-3.5 --bytecode-3.6 \
--bytecode-3.7 --bytecode-3.8
#: Check deparsing on selected bytecode 3.x
@@ -173,12 +182,24 @@ check-bytecode-2.3:
#: Check deparsing Python 2.4
check-bytecode-2.4:
$(PYTHON) test_pythonlib.py --bytecode-2.4-run --verify-run
$(PYTHON) test_pythonlib.py --bytecode-2.4
#: Check deparsing Python 2.5
check-bytecode-2.5:
$(PYTHON) test_pythonlib.py --bytecode-2.5-run --verify-run
$(PYTHON) test_pythonlib.py --bytecode-2.5
#: Check deparsing Python 2.6
check-bytecode-2.6:
$(PYTHON) test_pythonlib.py --bytecode-2.6-run --verify-run
$(PYTHON) test_pythonlib.py --bytecode-2.6 --syntax-verify
#: Check deparsing Python 2.7
check-bytecode-2.7:
$(PYTHON) test_pythonlib.py --bytecode-2.7-run --verify-run
$(PYTHON) test_pythonlib.py --bytecode-2.7 --syntax-verify
#: Get grammar coverage for Python 2.4
grammar-coverage-2.4:
-rm $(COVER_DIR)/spark-grammar-24.cover
@@ -251,16 +272,6 @@ grammar-coverage-3.7:
rm $(COVER_DIR)/spark-grammar-3.7.cover || /bin/true
SPARK_PARSER_COVERAGE=$(COVER_DIR)/spark-grammar-3.7.cover $(PYTHON) test_pyenvlib.py --3.7.3 --max=500
#: Check deparsing Python 2.6
check-bytecode-2.6:
$(PYTHON) test_pythonlib.py --bytecode-2.6-run --verify-run
$(PYTHON) test_pythonlib.py --bytecode-2.6 --syntax-verify
#: Check deparsing Python 2.7
check-bytecode-2.7:
$(PYTHON) test_pythonlib.py --bytecode-2.7-run --verify-run
$(PYTHON) test_pythonlib.py --bytecode-2.7 --syntax-verify
#: Check deparsing Python 3.0
check-bytecode-3.0:
$(PYTHON) test_pythonlib.py --bytecode-3.0-run --verify-run
@@ -347,11 +358,16 @@ check-bytecode-pypy3.6: 7.1
#: PyPy 5.0.x with Python 3.6.9
check-bytecode-pypy3.6: 7.2 7.3
7.3 7.2:
7.2:
$(PYTHON) test_pythonlib.py --bytecode-pypy3.6-run --verify-run
$(PYTHON) test_pythonlib.py --bytecode-pypy3.6 --verify
7.3:
$(PYTHON) test_pythonlib.py --bytecode-pypy3.7 --verify-run
# Pyston 2.3
2.3: check-3.8
clean: clean-py-dis clean-dis clean-unverified

View File

@@ -1,24 +1,49 @@
#!/usr/bin/env python
""" Trivial helper program to bytecompile and run an uncompile
""" Trivial helper program to byte compile and uncompile the bytecode file.
"""
import os, sys, py_compile
from xdis.version_info import version_tuple_to_str, PYTHON_VERSION_TRIPLE
assert len(sys.argv) >= 2
if len(sys.argv) < 2:
print("Usage: add-test.py [--run] *python-source*... [optimize-level]")
sys.exit(1)
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"
assert len(sys.argv) >= 3
py_source = sys.argv[2:]
i = 2
else:
suffix = ""
py_source = sys.argv[1:]
i = 1
try:
optimize = int(sys.argv[-1])
assert sys.argv >= i + 2
py_source = sys.argv[i:-1]
i = 2
except:
optimize = 2
for path in py_source:
short = os.path.basename(path)
if short.endswith(".py"):
short = short[: -len(".py")]
if hasattr(sys, "pypy_version_info"):
cfile = "bytecode_pypy%s%s/%s" % (version, suffix, short) + "c"
version = version_tuple_to_str(end=2, delimiter="")
bytecode = "bytecode_pypy%s%s/%spy%s.pyc" % (version, suffix, short, version)
else:
cfile = "bytecode_%s%s/%s" % (version, suffix, short) + "c"
print("byte-compiling %s to %s" % (path, cfile))
py_compile.compile(path, cfile)
if isinstance(version, str) or version >= (2, 6, 0):
os.system("../bin/uncompyle6 -a -T %s" % cfile)
version = version_tuple_to_str(end=2)
bytecode = "bytecode_%s%s/%s.pyc" % (version, suffix, short)
print("byte-compiling %s to %s" % (path, bytecode))
if PYTHON_VERSION_TRIPLE >= (3, 2):
py_compile.compile(path, bytecode, optimize=optimize)
else:
py_compile.compile(path, bytecode)
if PYTHON_VERSION_TRIPLE >= (2, 6):
os.system("../bin/uncompyle6 -a -t %s" % bytecode)

Binary file not shown.

BIN
test/bytecode_1.0/stat.pyc Normal file

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

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