You've already forked python-uncompyle6
mirror of
https://github.com/rocky/python-uncompyle6.git
synced 2025-08-04 01:09:52 +08:00
Compare commits
74 Commits
release-2.
...
release-2.
Author | SHA1 | Date | |
---|---|---|---|
|
4377354cf9 | ||
|
6caa2c12fa | ||
|
3153a955d4 | ||
|
6f3a88d7e2 | ||
|
109737cbef | ||
|
05733c6171 | ||
|
6765a2ea97 | ||
|
c85496a92d | ||
|
e4ba73adfb | ||
|
7bf93980ce | ||
|
8241a5e3a8 | ||
|
faac11ad8c | ||
|
fe04b97c6b | ||
|
62f6220082 | ||
|
11e6eff427 | ||
|
2286aa5320 | ||
|
72ac7eb27c | ||
|
a8c5f71cfe | ||
|
feec241da8 | ||
|
c5f359f9be | ||
|
bfe8357f52 | ||
|
ceb47aba9c | ||
|
08720474bf | ||
|
119bb9bb26 | ||
|
4455b5e280 | ||
|
dcbf8d2cf7 | ||
|
b52baddab6 | ||
|
03bb54f8ea | ||
|
313e468bdc | ||
|
dc80b140c6 | ||
|
fa48c9fc61 | ||
|
0a32a16d88 | ||
|
4aa703d727 | ||
|
f3a4e6ee54 | ||
|
43f5c5dcca | ||
|
3e49aa56bb | ||
|
9cc9fc99c2 | ||
|
2ebc558b40 | ||
|
34a582b64c | ||
|
2711c8d06f | ||
|
40badefe9d | ||
|
d9ef5ff69a | ||
|
a4e839960f | ||
|
7b3c7e83ec | ||
|
1b71d0a049 | ||
|
17b0caa4f0 | ||
|
b88e97c17d | ||
|
158bdd9b04 | ||
|
b0d3a4e47b | ||
|
4ba2eb6981 | ||
|
76768c889a | ||
|
8ae7e22f2e | ||
|
7e0526d627 | ||
|
2c7fcf9e62 | ||
|
5a813621cb | ||
|
9f7d36f8fb | ||
|
4e57c3da5b | ||
|
0de3efb01a | ||
|
fff4283f73 | ||
|
551e2174cb | ||
|
f25c9b45a4 | ||
|
077bca6141 | ||
|
31ebe88b38 | ||
|
bc2a36b9f7 | ||
|
66739752d8 | ||
|
716ee6d361 | ||
|
ca00e433b7 | ||
|
f0cc2df543 | ||
|
52da6f4a8f | ||
|
54a0af733b | ||
|
2927921856 | ||
|
cd480c8670 | ||
|
7d42329c31 | ||
|
b89177d234 |
3
.gitignore
vendored
3
.gitignore
vendored
@@ -3,9 +3,12 @@
|
||||
/.cache
|
||||
/.eggs
|
||||
/.python-version
|
||||
/.tox
|
||||
/README
|
||||
/__pkginfo__.pyc
|
||||
/dist
|
||||
/how-to-make-a-release.txt
|
||||
/tmp
|
||||
/uncompyle6.egg-info
|
||||
__pycache__
|
||||
build
|
||||
|
@@ -3,12 +3,14 @@ language: python
|
||||
sudo: false
|
||||
|
||||
python:
|
||||
- '2.6'
|
||||
- '2.7'
|
||||
- '3.4'
|
||||
- '3.5'
|
||||
- '2.7'
|
||||
- '2.6'
|
||||
- '3.4'
|
||||
- '3.2'
|
||||
|
||||
install:
|
||||
- pip install -r requirements.txt
|
||||
- pip install -r requirements-dev.txt
|
||||
|
||||
script:
|
||||
|
348
ChangeLog
348
ChangeLog
@@ -1,6 +1,352 @@
|
||||
2016-05-05 rocky <rocky@gnu.org>
|
||||
|
||||
* uncompyle6/version.py: Get ready for release 2.3.4
|
||||
|
||||
2016-05-05 rocky <rocky@gnu.org>
|
||||
|
||||
* .travis.yml: Remove pypy3 add python 3.2 testing Reorder list for testing preference
|
||||
|
||||
2016-05-05 rocky <rocky@gnu.org>
|
||||
|
||||
* .travis.yml: Remove pypy
|
||||
|
||||
2016-05-05 rocky <rocky@gnu.org>
|
||||
|
||||
* Makefile, test/Makefile, uncompyle6/semantics/pysource.py: Fix up
|
||||
3.2 tests Remove pypy
|
||||
|
||||
2016-05-05 rocky <rocky@gnu.org>
|
||||
|
||||
* .travis.yml: Try pypy and pypy3
|
||||
|
||||
2016-05-05 rocky <rocky@gnu.org>
|
||||
|
||||
* test/simple_source/def/05_abc_class.py,
|
||||
test/simple_source/def/06_classbug.py, uncompyle6/parsers/parse3.py:
|
||||
Python 3.5 abc.py bug distilled
|
||||
|
||||
2016-05-05 rocky <rocky@gnu.org>
|
||||
|
||||
* uncompyle6/scanners/dis35.py, uncompyle6/scanners/scanner35.py:
|
||||
Add cross-Python-protable 3.5 dis module
|
||||
|
||||
2016-05-04 rocky <rocky@gnu.org>
|
||||
|
||||
* test/simple_source/stmts/05_with.py,
|
||||
uncompyle6/opcodes/opcode_35.py, uncompyle6/parser.py,
|
||||
uncompyle6/parsers/parse3.py, uncompyle6/scanners/scanner35.py:
|
||||
Handle 3.5 with [as] scanner35.py: Fix a small variable-name typo
|
||||
|
||||
2016-05-03 rocky <rocky@gnu.org>
|
||||
|
||||
* : One more test
|
||||
|
||||
2016-05-03 rocky <rocky@gnu.org>
|
||||
|
||||
* uncompyle6/scanners/scanner3.py,
|
||||
uncompyle6/scanners/scanner34.py, uncompyle6/scanners/scanner35.py:
|
||||
Don't repeat next_except_jump
|
||||
|
||||
2016-05-03 rocky <rb@dustyfeet.com>
|
||||
|
||||
* __pkginfo__.py, requirements.txt: Wrong package name
|
||||
|
||||
2016-05-03 rocky <rocky@gnu.org>
|
||||
|
||||
* __pkginfo__.py, requirements.txt, setup.py: More package
|
||||
administrivia
|
||||
|
||||
2016-05-03 rocky <rocky@gnu.org>
|
||||
|
||||
* uncompyle6/scanner.py: Remove one more old-style Python class
|
||||
|
||||
2016-05-03 rocky <rocky@gnu.org>
|
||||
|
||||
* uncompyle6/scanners/scanner27.py: DRY Python 2.7 scanner more
|
||||
|
||||
2016-05-03 rocky <rocky@gnu.org>
|
||||
|
||||
* MANIFEST.in: Include LICENSE in package
|
||||
|
||||
2016-05-03 rocky <rocky@gnu.org>
|
||||
|
||||
* ChangeLog, NEWS, uncompyle6/version.py: Get ready for release
|
||||
2.3.3
|
||||
|
||||
2016-05-02 rocky <rocky@gnu.org>
|
||||
|
||||
* README.rst: Be more explicit that we need Python 2.6 or later
|
||||
|
||||
2016-05-02 rocky <rocky@gnu.org>
|
||||
|
||||
* : commit feec241da88107b97bbdfbabeb3ae7131a7aa923 Author: rocky
|
||||
<rocky@gnu.org> Date: Mon May 2 21:20:17 2016 -0400
|
||||
|
||||
2016-05-02 rocky <rb@dustyfeet.com>
|
||||
|
||||
* README.rst: Note relation to other uncompyle forks Add some other minor corrections and additions as well.
|
||||
|
||||
2016-05-02 rocky <rb@dustyfeet.com>
|
||||
|
||||
* uncompyle6/__init__.py: Trivial spacing change
|
||||
|
||||
2016-05-02 rocky <rocky@gnu.org>
|
||||
|
||||
* ChangeLog, NEWS, __pkginfo__.py, bin/pydisassemble,
|
||||
bin/uncompyle6, setup.py, uncompyle6/__init__.py,
|
||||
uncompyle6/version.py: Add -V | --version and simplfy changing it
|
||||
|
||||
2016-05-01 rocky <rocky@gnu.org>
|
||||
|
||||
* uncompyle6/__init__.py: Expose uncompyle_file
|
||||
|
||||
2016-05-01 rocky <rocky@gnu.org>
|
||||
|
||||
* test/Makefile, uncompyle6/semantics/pysource.py: Bug
|
||||
|
||||
2016-05-01 rocky <rocky@gnu.org>
|
||||
|
||||
* test/Makefile, test/simple_source/expression/05_const_map.py: Add
|
||||
test for last fix. Drop 2.5 test until we figure out what's wrong
|
||||
|
||||
2016-05-01 rocky <rocky@gnu.org>
|
||||
|
||||
* uncompyle6/parsers/parse3.py, uncompyle6/scanners/scanner35.py,
|
||||
uncompyle6/semantics/pysource.py: Bug in 3.5 constant map parsing
|
||||
|
||||
2016-05-01 rocky <rocky@gnu.org>
|
||||
|
||||
* uncompyle6/__init__.py: Export module load and fns load_file,
|
||||
load_module
|
||||
|
||||
2016-05-01 rocky <rocky@gnu.org>
|
||||
|
||||
* __pkginfo__.py, setup.py, uncompyle6/marsh.py: License is MIT marsh.py: remove unused import
|
||||
|
||||
2016-05-01 rocky <rocky@gnu.org>
|
||||
|
||||
* uncompyle6/parsers/parse3.py: Forgot to define Python3ParserSingle
|
||||
|
||||
2016-05-01 rocky <rocky@gnu.org>
|
||||
|
||||
* uncompyle6/parser.py, uncompyle6/parsers/parse2.py,
|
||||
uncompyle6/parsers/parse3.py: Start to DRY Python2 and Python3
|
||||
grammars Separate out 3.2, and 3.5+ specific grammar code
|
||||
|
||||
2016-04-30 rocky <rocky@gnu.org>
|
||||
|
||||
* ChangeLog, NEWS, README.rst, __pkginfo__.py: Get ready for release
|
||||
2.3.1
|
||||
|
||||
2016-04-30 rocky <rocky@gnu.org>
|
||||
|
||||
* uncompyle6/parsers/astnode.py, uncompyle6/parsers/parse3.py,
|
||||
uncompyle6/semantics/pysource.py: Python 3.0..3.2 bug in
|
||||
LOAD_FAST/STORE_LOCAL LOAD_FAST '__locals__' STORE_LOCALS '' Also have to adjust doc constants for this crap astnode.py: minor format change
|
||||
|
||||
2016-04-30 rocky <rocky@gnu.org>
|
||||
|
||||
* test/Makefile, test/simple_source/def/06_classbug.py,
|
||||
test/test_pythonlib.py: Test optimized Python code and Python 3.2
|
||||
|
||||
2016-04-30 rocky <rocky@gnu.org>
|
||||
|
||||
* uncompyle6/parsers/parse3.py: Pevious commit grammar change is
|
||||
Python 3.5 and up
|
||||
|
||||
2016-04-30 rocky <rocky@gnu.org>
|
||||
|
||||
* uncompyle6/parsers/parse3.py: Python 3.5 if statments decompyle Sometimes it doesn't need JUMP_FORWARD _come_from _come_from For example: def handle2(module): if module == 'foo': try: module = 1 except ImportError as exc: module = exc return module And: if __name__: for i in (1, 2): x = 3
|
||||
|
||||
2016-04-28 rocky <rocky@gnu.org>
|
||||
|
||||
* requirements.txt, uncompyle6/parser.py,
|
||||
uncompyle6/parsers/parse2.py, uncompyle6/parsers/parse3.py,
|
||||
uncompyle6/semantics/fragments.py, uncompyle6/semantics/pysource.py:
|
||||
spark -> spark_parser
|
||||
|
||||
2016-04-28 rocky <rocky@gnu.org>
|
||||
|
||||
* uncompyle6/parsers/spark.py: Really remove spark - Use external
|
||||
package instead
|
||||
|
||||
2016-04-27 R. Bernstein <rocky@users.noreply.github.com>
|
||||
|
||||
* : Merge pull request #8 from rocky/external-spark External spark
|
||||
|
||||
2016-04-27 rocky <rocky@gnu.org>
|
||||
|
||||
* .travis.yml, circle.yml: Note dependencies on spark
|
||||
|
||||
2016-04-27 rocky <rocky@gnu.org>
|
||||
|
||||
* .gitignore, README.rst, requirements.txt, uncompyle6/parser.py,
|
||||
uncompyle6/parsers/astnode.py, uncompyle6/parsers/parse2.py,
|
||||
uncompyle6/parsers/parse3.py, uncompyle6/semantics/fragments.py,
|
||||
uncompyle6/semantics/pysource.py: Use external spark now.
|
||||
|
||||
2016-04-20 rocky <rocky@gnu.org>
|
||||
|
||||
* circle.yml: Back to 2.7.8
|
||||
|
||||
2016-04-20 rocky <rocky@gnu.org>
|
||||
|
||||
* circle.yml: Try python 2.7.10
|
||||
|
||||
2016-04-19 rocky <rocky@gnu.org>
|
||||
|
||||
* README.rst: Remove link to Mysterie uncompyle2 per request
|
||||
|
||||
2016-04-19 rocky <rocky@gnu.org>
|
||||
|
||||
* ChangeLog, NEWS, __pkginfo__.py: Get ready for release 2.2.0
|
||||
|
||||
2016-04-18 rocky <rocky@gnu.org>
|
||||
|
||||
* README.rst: Another typo
|
||||
|
||||
2016-04-18 R. Bernstein <rocky@users.noreply.github.com>
|
||||
|
||||
* : Merge pull request #7 from rocky/single-compile Support single-mode compile
|
||||
|
||||
2016-04-18 rocky <rocky@gnu.org>
|
||||
|
||||
* README.rst: Doc typo
|
||||
|
||||
2016-04-18 Thomas Grainger <tom.grainger@procensus.com>
|
||||
|
||||
* __pkginfo__.py, setup.cfg, setup.py: declare Python3 support in
|
||||
wheel and trove
|
||||
|
||||
2016-04-18 rocky <rocky@gnu.org>
|
||||
|
||||
* uncompyle6/parser.py, uncompyle6/parsers/parse2.py,
|
||||
uncompyle6/parsers/parse3.py: Start to DRY Python 2 and Python 3
|
||||
grammar code Move common code to parser.py
|
||||
|
||||
2016-04-18 rocky <rocky@gnu.org>
|
||||
|
||||
* pytest/test_single_compile.py, uncompyle6/parser.py,
|
||||
uncompyle6/parsers/parse2.py, uncompyle6/parsers/parse3.py: Add
|
||||
simgle-mode compilation
|
||||
|
||||
2016-04-17 rocky <rocky@gnu.org>
|
||||
|
||||
* pytest/test_single_compile.py, uncompyle6/parser.py,
|
||||
uncompyle6/parsers/parse2.py, uncompyle6/parsers/parse3.py,
|
||||
uncompyle6/semantics/pysource.py: Towards single compilation
|
||||
|
||||
2016-04-10 rocky <rb@dustyfeet.com>
|
||||
|
||||
* : Back off if_else_ternary pending Fails on Python 3.4 investigation Python 3.5 works though
|
||||
|
||||
2016-04-10 rocky <rb@dustyfeet.com>
|
||||
|
||||
* .gitignore: Test administrivia
|
||||
|
||||
2016-04-07 rocky <rb@dustyfeet.com>
|
||||
|
||||
* HISTORY.md, README.rst,
|
||||
test/simple_source/branching/10_if_else_ternary.py,
|
||||
uncompyle6/parsers/parse2.py, uncompyle6/parsers/parse3.py: Handle
|
||||
Ternary "or". Remove mention of uncompyle3 uncompyle3 removed per Mysterie's request [Fixes Issue #5]
|
||||
|
||||
2016-03-11 rocky <rb@dustyfeet.com>
|
||||
|
||||
* test/Makefile: remove uncompyle3 and make test work again * uncompyle3 removed by request * make test on python 2.7 is failing on some python3 and python3.5 bytecodes. Remove for now.
|
||||
|
||||
2016-02-23 R. Bernstein <rocky@users.noreply.github.com>
|
||||
|
||||
* : Merge pull request #3 from lelicopter/master Bug correction (parse cmd options)
|
||||
|
||||
2016-01-07 rocky <rb@dustyfeet.com>
|
||||
|
||||
* test/Makefile, test/bytecompile-tests, test/test_pythonlib.py: Add
|
||||
Python 3.5 tests that we can do.
|
||||
|
||||
2016-01-05 R. Bernstein <rocky@users.noreply.github.com>
|
||||
|
||||
* HISTORY.md: Grammar fixes
|
||||
|
||||
2016-01-02 rocky <rb@dustyfeet.com>
|
||||
|
||||
* ChangeLog, NEWS, __pkginfo__.py: Get ready for release 2.1.3
|
||||
|
||||
2016-01-02 rocky <rb@dustyfeet.com>
|
||||
|
||||
* uncompyle6/opcodes/opcode_23.py, uncompyle6/opcodes/opcode_25.py,
|
||||
uncompyle6/opcodes/opcode_26.py, uncompyle6/opcodes/opcode_27.py,
|
||||
uncompyle6/opcodes/opcode_32.py, uncompyle6/opcodes/opcode_33.py,
|
||||
uncompyle6/opcodes/opcode_34.py, uncompyle6/opcodes/opcode_35.py,
|
||||
uncompyle6/opcodes/opcode_3x.py, uncompyle6/parser.py,
|
||||
uncompyle6/scanner.py, uncompyle6/scanners/scanner32.py,
|
||||
uncompyle6/scanners/scanner33.py, uncompyle6/scanners/scanner34.py,
|
||||
uncompyle6/scanners/scanner35.py: Start to DRY opcode code. Limited
|
||||
support for decopyling Python 3.5
|
||||
|
||||
2016-01-02 rocky <rb@dustyfeet.com>
|
||||
|
||||
* test/Makefile, test/ok_lib3.4/antigravity.py,
|
||||
test/ok_lib3.4/bisect.py, test/test_pythonlib.py: Start 3.4 library
|
||||
verify tests
|
||||
|
||||
2016-01-02 rocky <rb@dustyfeet.com>
|
||||
|
||||
* README.rst: Regularize spelling of bytecode
|
||||
|
||||
2016-01-02 rocky <rb@dustyfeet.com>
|
||||
|
||||
* Makefile, README.rst: Add download shield. Add check-rst target
|
||||
|
||||
2016-01-02 R. Bernstein <rocky@users.noreply.github.com>
|
||||
|
||||
* README.rst: Update README.rst
|
||||
|
||||
2016-01-02 rocky <rb@dustyfeet.com>
|
||||
|
||||
* uncompyle6/semantics/fragments.py: Track recent source class
|
||||
semantic actions in fragment actions
|
||||
|
||||
2016-01-02 rocky <rb@dustyfeet.com>
|
||||
|
||||
* uncompyle6/scanner.py, uncompyle6/scanners/scanner25.py,
|
||||
uncompyle6/scanners/scanner26.py, uncompyle6/scanners/scanner27.py:
|
||||
Make ScannerXX() initialization the same on Python 2.x and 3.x
|
||||
|
||||
2016-01-02 rocky <rb@dustyfeet.com>
|
||||
|
||||
* test/Makefile,
|
||||
test/simple_source/comprehension/05_list_comprehension.py,
|
||||
test/simple_source/def/02_closure.py, test/test_pythonlib.py,
|
||||
uncompyle6/main.py, uncompyle6/verify.py: Verify 3.4 bytecode.
|
||||
verify API call bug fixed.
|
||||
|
||||
2016-01-02 rocky <rb@dustyfeet.com>
|
||||
|
||||
* test/simple_source/def/05_class.py, uncompyle6/load.py,
|
||||
uncompyle6/main.py, uncompyle6/parsers/parse3.py,
|
||||
uncompyle6/semantics/pysource.py: Python 3 class deparsing. stop
|
||||
earlier in uncompyle6 on a syntax error.
|
||||
|
||||
2016-01-01 rocky <rb@dustyfeet.com>
|
||||
|
||||
* uncompyle6/scanners/scanner3.py: Fix make_closure compilation from
|
||||
2.x of 3.3 bytecode
|
||||
|
||||
2016-01-01 rocky <rb@dustyfeet.com>
|
||||
|
||||
* test/simple_source/def/02_closure.py,
|
||||
uncompyle6/parsers/parse3.py, uncompyle6/semantics/pysource.py: Work
|
||||
on MAKE_CLOSURE rules for Python 3.3
|
||||
|
||||
2015-12-31 rocky <rb@dustyfeet.com>
|
||||
|
||||
* __pkginfo__.py: Get ready for release 2.1.2
|
||||
* uncompyle6/semantics/fragments.py: track source deparsing
|
||||
superclass bug fix
|
||||
|
||||
2015-12-31 rocky <rb@dustyfeet.com>
|
||||
|
||||
* ChangeLog, NEWS, __pkginfo__.py: Get ready for release 2.1.2
|
||||
|
||||
2015-12-31 rocky <rb@dustyfeet.com>
|
||||
|
||||
|
11
HISTORY.md
11
HISTORY.md
@@ -30,7 +30,7 @@ The last mention of a release of SPARK from John is around 2002.
|
||||
|
||||
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 subsequennt public release announcement that I can find is
|
||||
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).
|
||||
|
||||
From the CHANGES file found in
|
||||
@@ -38,9 +38,8 @@ From the CHANGES file found in
|
||||
it appears that Hartmut did most of the work to get this code to
|
||||
accept the full Python language. He added precidence to the table
|
||||
specifiers, support for multiple versions of Python, the
|
||||
pretty-printing of docstrings, lists and hashes. He also wrote
|
||||
extensive tests and routines to the testing and verification of
|
||||
decompiled bytecode.
|
||||
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 could verify against the entire Python library.
|
||||
|
||||
decompyle2.2 was packaged for Debian (sarge) by
|
||||
[Ben Burton around 2002](https://packages.qa.debian.org/d/decompyle.html). As
|
||||
@@ -91,10 +90,6 @@ Hartmut a decade an a half ago:
|
||||
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
|
||||
|
||||
One of the attempts to modernize it and make it available for Python3
|
||||
is [the one by Anton Vorobyov (DarkFenX)](https://github.com/DarkFenX/uncompyle3). I've
|
||||
followed some of the ideas there in this project.
|
||||
|
||||
Lastly, I should mention [unpyc](https://code.google.com/p/unpyc3/)
|
||||
and most especially [pycdc](https://github.com/zrax/pycdc), largely by
|
||||
Michael Hansen and Darryl Pogue. If they supported getting source-code
|
||||
|
@@ -1,6 +1,7 @@
|
||||
include README.rst
|
||||
include HISTORY.md
|
||||
include ChangeLog
|
||||
include HISTORY.md
|
||||
include LICENSE
|
||||
include __pkginfo__.py
|
||||
recursive-include uncompyle6 *.py
|
||||
include bin/uncompyle6
|
||||
|
7
Makefile
7
Makefile
@@ -28,7 +28,7 @@ check-2.7 check-3.3 check-3.4: pytest
|
||||
$(MAKE) -C test $@
|
||||
|
||||
#: Tests for Python 3.5 - pytest doesn't work here
|
||||
check-3.5:
|
||||
check-3.2 check-3.5:
|
||||
$(MAKE) -C test $@
|
||||
|
||||
#:Tests for Python 2.6 (doesn't have pytest)
|
||||
@@ -60,6 +60,11 @@ sdist:
|
||||
#: Style check. Set env var LINT to pyflakes, flake, or flake8
|
||||
lint: flake8
|
||||
|
||||
# Check StructuredText long description formatting
|
||||
check-rst:
|
||||
$(PYTHON) setup.py --long-description | rst2html.py > python3-trepan.html
|
||||
|
||||
#: Lint program
|
||||
flake8:
|
||||
$(LINT) uncompyle6
|
||||
|
||||
|
49
NEWS
49
NEWS
@@ -1,3 +1,52 @@
|
||||
uncompyle6 2.3.4 2016-05-5
|
||||
|
||||
- More Python 3.5 parsing bugs addressed
|
||||
- decompiling Python 3.5 from other Python versions works
|
||||
- test from Python 3.2
|
||||
- remove "__module__ = __name__" in 3.0 <= Python 3.2
|
||||
|
||||
uncompyle6 2.3.3 2016-05-3
|
||||
|
||||
- Fix bug in running uncompyle6 script on Python 3
|
||||
- Speed up performance on deparsing long lists by grouping in chunks of 32 and 256 items
|
||||
- DRY Python expressions between Python 2 and 3
|
||||
|
||||
uncompyle6 2.3.2 2016-05-1
|
||||
|
||||
- Add --version option standalone scripts
|
||||
- Correct License information in package
|
||||
- expose fns uncompyle_file, load_file, and load_module
|
||||
- Start to DRY Python2 and Python3 grammars Separate out 3.2, and 3.5+
|
||||
specific grammar code
|
||||
- Fix bug in 3.5+ constant map parsing
|
||||
|
||||
uncompyle6 2.3.0, 2.3.1 2016-04-30
|
||||
|
||||
- Require spark_parser >= 1.1.0
|
||||
|
||||
uncompyle6 2.2.0 2016-04-30
|
||||
|
||||
- Spark is no longer here but pulled separate package spark_parse
|
||||
- Python 3 parsing fixes
|
||||
- More tests
|
||||
|
||||
uncompyle6 2.2.0 2016-04-02
|
||||
|
||||
- Support single-mode (in addtion to exec-mode) compilation
|
||||
- Start to DRY Python 2 and Python 3 grammars
|
||||
- Fix bug in if else ternary construct
|
||||
- Fix bug in uncomplye6 -d and -r options (via lelicopter)
|
||||
|
||||
|
||||
uncompyle6 2.1.3 2016-01-02
|
||||
|
||||
- Limited support for decompiling Python 3.5
|
||||
- Improve Python 3 class deparsing
|
||||
- Handle MAKE_CLOSURE opcode
|
||||
- Start to DRY opcode code.
|
||||
- increase test coverage
|
||||
- fix misc small bugs and some improvements
|
||||
|
||||
uncompyle6 2.1.2 2015-12-31
|
||||
|
||||
- Fix cross-version Marshal loading
|
||||
|
42
README.rst
42
README.rst
@@ -3,28 +3,33 @@
|
||||
uncompyle6
|
||||
==========
|
||||
|
||||
A native Python Byte-code Disassembler, Decompiler, Fragment Decompiler
|
||||
and byte-code library
|
||||
A native Python bytecode Disassembler, Decompiler, Fragment Decompiler
|
||||
and bytecode library. Follows in the tradition of decompyle, uncompyle, and uncompyle2.
|
||||
|
||||
|
||||
Introduction
|
||||
------------
|
||||
|
||||
*uncompyle6* translates Python byte-code back into equivalent Python
|
||||
source code. It accepts byte-codes from Python version 2.5 to 3.4 or
|
||||
so and has been tested on Python running versions 2.6, 2.7, 3.3,
|
||||
3.4 and 3.5.
|
||||
*uncompyle6* translates Python bytecode back into equivalent Python
|
||||
source code. It accepts bytecodes from Python version 2.5 to 3.4 or
|
||||
so. The code requires Python 2.6 or later and has been tested on Python
|
||||
running versions 2.6, 2.7, 3.3, 3.4 and 3.5.
|
||||
|
||||
Why this?
|
||||
---------
|
||||
|
||||
What makes this different other CPython byte-code decompilers? Its
|
||||
There were a number of decompyle, uncompile, uncompyle2, uncompyle3
|
||||
forks around. All of them come basically from the same code base, and
|
||||
almost all of them not maintained very well. This code pulls these together
|
||||
and addresses a number of open issues in those.
|
||||
|
||||
What makes this different from other CPython bytecode decompilers? Its
|
||||
ability to deparse just fragments and give source-code information
|
||||
around a given bytecode offset.
|
||||
|
||||
I using this to deparse fragments of code inside my trepan_
|
||||
I use this to deparse fragments of code inside my trepan_
|
||||
debuggers_. For that, I need to record text fragments for all
|
||||
byte-code offsets (of interest). This purpose although largely
|
||||
bytecode offsets (of interest). This purpose although largely
|
||||
compatible with the original intention is yet a little bit different.
|
||||
See this_ for more information.
|
||||
|
||||
@@ -37,7 +42,7 @@ information.
|
||||
Other parts of the library can be used inside Python for various
|
||||
bytecode-related tasks. For example you can read in bytecode,
|
||||
i.e. perform a version-independent `marshal.loads()`, and disassemble
|
||||
the bytecode using version of Python different from the one used to
|
||||
the bytecode using a version of Python different from the one used to
|
||||
compile the bytecode.
|
||||
|
||||
|
||||
@@ -48,6 +53,8 @@ This uses setup.py, so it follows the standard Python routine:
|
||||
|
||||
::
|
||||
|
||||
pip install -r requirements.txt
|
||||
pip install -r requirements-dev.txt
|
||||
python setup.py install # may need sudo
|
||||
# or if you have pyenv:
|
||||
python setup.py develop
|
||||
@@ -77,27 +84,28 @@ Run
|
||||
::
|
||||
|
||||
./bin/uncompyle6 -h
|
||||
./bin/pydisassemble -y
|
||||
./bin/pydisassemble -h
|
||||
|
||||
for usage help
|
||||
for usage help.
|
||||
|
||||
|
||||
Known Bugs/Restrictions
|
||||
-----------------------
|
||||
|
||||
Python 2 deparsing is probably as solid as the various versions of
|
||||
uncompyle2. Python 3 deparsing is okay but not as solid.
|
||||
uncompyle2. Python 3 deparsing is okay but not as solid. Python 3.5 is missing some of new opcodes added, but still often works.
|
||||
|
||||
See Also
|
||||
--------
|
||||
|
||||
* https://github.com/zrax/pycdc
|
||||
* https://github.com/Mysterie/uncompyle2
|
||||
* https://github.com/DarkFenX/uncompyle3
|
||||
* https://code.google.com/p/unpyc3/
|
||||
* https://github.com/zrax/pycdc : supports all versions of Python and is written in C++
|
||||
* https://code.google.com/archive/p/unpyc3/ : supports Python 3.2 only
|
||||
|
||||
The above projects use a different decompiling technique what is used here.
|
||||
|
||||
The HISTORY file.
|
||||
|
||||
.. |downloads| image:: https://img.shields.io/pypi/dd/uncompyle6.svg
|
||||
.. _trepan: https://pypi.python.org/pypi/trepan
|
||||
.. _debuggers: https://pypi.python.org/pypi/trepan3k
|
||||
.. _remake: https://bashdb.sf.net/remake
|
||||
|
@@ -9,13 +9,20 @@
|
||||
|
||||
# Things that change more often go here.
|
||||
copyright = """
|
||||
Copyright (C) 2015 Rocky Bernstein <rb@dustyfeet.com>.
|
||||
Copyright (C) 2015, 2016 Rocky Bernstein <rb@dustyfeet.com>.
|
||||
"""
|
||||
|
||||
classifiers = ['Development Status :: 3 - Alpha',
|
||||
classifiers = ['Development Status :: 4 - Beta',
|
||||
'Intended Audience :: Developers',
|
||||
'Operating System :: OS Independent',
|
||||
'Programming Language :: Python',
|
||||
'Programming Language :: Python :: 2',
|
||||
'Programming Language :: Python :: 2.6',
|
||||
'Programming Language :: Python :: 2.7',
|
||||
'Programming Language :: Python :: 3',
|
||||
'Programming Language :: Python :: 3.3',
|
||||
'Programming Language :: Python :: 3.4',
|
||||
'Programming Language :: Python :: 3.5',
|
||||
'Topic :: Software Development :: Debuggers',
|
||||
'Topic :: Software Development :: Libraries :: Python Modules',
|
||||
]
|
||||
@@ -24,7 +31,10 @@ classifiers = ['Development Status :: 3 - Alpha',
|
||||
author = "Rocky Bernstein, Hartmut Goebel, John Aycock, and others"
|
||||
author_email = "rb@dustyfeet.com"
|
||||
ftp_url = None
|
||||
# license = 'BSDish'
|
||||
install_requires = ['spark-parser >= 1.1.1']
|
||||
license = 'GPL'
|
||||
|
||||
license = 'MIT'
|
||||
mailing_list = 'python-debugger@googlegroups.com'
|
||||
modname = 'uncompyle6'
|
||||
packages = ['uncompyle6', 'uncompyle6.opcodes', 'uncompyle6.semantics', 'uncompyle6.scanners', 'uncompyle6.parsers']
|
||||
@@ -40,7 +50,6 @@ def get_srcdir():
|
||||
return os.path.realpath(filename)
|
||||
|
||||
ns = {}
|
||||
version = '2.1.2'
|
||||
web = 'https://github.com/rocky/python-uncompyle6/'
|
||||
|
||||
# tracebacks in zip files are funky and not debuggable
|
||||
|
@@ -1,7 +1,7 @@
|
||||
#!/usr/bin/env python
|
||||
# Mode: -*- python -*-
|
||||
#
|
||||
# Copyright (c) 2015 by Rocky Bernstein <rb@dustyfeet.com>
|
||||
# Copyright (c) 2015-2016 by Rocky Bernstein <rb@dustyfeet.com>
|
||||
#
|
||||
from __future__ import print_function
|
||||
import sys, os, getopt
|
||||
@@ -9,11 +9,13 @@ import sys, os, getopt
|
||||
program = os.path.basename(__file__)
|
||||
|
||||
__doc__ = """
|
||||
Usage: %s [OPTIONS]... FILE
|
||||
Usage:
|
||||
%s [OPTIONS]... FILE
|
||||
%s [--help | -h | -V | --version]
|
||||
|
||||
Examples:
|
||||
%s foo.pyc
|
||||
%s foo.py
|
||||
%s foo.pyc
|
||||
%s foo.py
|
||||
%s -o foo.pydis foo.pyc
|
||||
%s -o /tmp foo.pyc
|
||||
|
||||
@@ -24,7 +26,7 @@ Options:
|
||||
<path>
|
||||
--help show this message
|
||||
|
||||
""" % ((program,) * 5)
|
||||
""" % ((program,) * 6)
|
||||
|
||||
|
||||
Usage_short = \
|
||||
@@ -32,6 +34,7 @@ Usage_short = \
|
||||
|
||||
from uncompyle6 import check_python_version
|
||||
from uncompyle6.disas import disassemble_files
|
||||
from uncompyle6.version import VERSION
|
||||
|
||||
check_python_version(program)
|
||||
|
||||
@@ -40,7 +43,7 @@ out_base = None
|
||||
|
||||
|
||||
try:
|
||||
opts, files = getopt.getopt(sys.argv[1:], 'ho:', ['help'])
|
||||
opts, files = getopt.getopt(sys.argv[1:], 'hVo:', ['help', 'version'])
|
||||
except getopt.GetoptError as e:
|
||||
print('%s: %s' % (os.path.basename(sys.argv[0]), e), file=sys.stderr)
|
||||
sys.exit(-1)
|
||||
@@ -48,6 +51,9 @@ except getopt.GetoptError as e:
|
||||
for opt, val in opts:
|
||||
if opt in ('-h', '--help'):
|
||||
print(__doc__)
|
||||
sys.exit(1)
|
||||
elif opt in ('-V', '--version'):
|
||||
print("%s %s" % (program, VERSION))
|
||||
sys.exit(0)
|
||||
elif opt == '-o':
|
||||
outfile = val
|
||||
|
@@ -1,16 +1,23 @@
|
||||
#!/usr/bin/env python
|
||||
# Mode: -*- python -*-
|
||||
#
|
||||
# Copyright (c) 2015-2016 by Rocky Bernstein
|
||||
# Copyright (c) 2000-2002 by hartmut Goebel <h.goebel@crazy-compilers.com>
|
||||
# Copyright (c) 2015 by Rocky Bernstein
|
||||
#
|
||||
from __future__ import print_function
|
||||
import sys, os, getopt, time
|
||||
|
||||
"""
|
||||
Usage: uncompyle6 [OPTIONS]... [ FILE | DIR]...
|
||||
program = os.path.basename(__file__)
|
||||
|
||||
__doc__ = """
|
||||
Usage:
|
||||
%s [OPTIONS]... [ FILE | DIR]...
|
||||
%s [--help | -h | --V | --version]
|
||||
|
||||
Examples:
|
||||
uncompyle6 foo.pyc bar.pyc # decompile foo.pyc, bar.pyc to stdout
|
||||
uncompyle6 -o . foo.pyc bar.pyc # decompile to ./foo.pyc_dis and ./bar.pyc_dis
|
||||
uncompyle6 -o /tmp /usr/lib/python1.5 # decompile whole library
|
||||
%s foo.pyc bar.pyc # decompile foo.pyc, bar.pyc to stdout
|
||||
%s -o . foo.pyc bar.pyc # decompile to ./foo.pyc_dis and ./bar.pyc_dis
|
||||
%s -o /tmp /usr/lib/python1.5 # decompile whole library
|
||||
|
||||
Options:
|
||||
-o <path> output decompiled files to this path:
|
||||
@@ -34,26 +41,25 @@ Options:
|
||||
Debugging Options:
|
||||
--asm -a include byte-code (disables --verify)
|
||||
--grammar -g show matching grammar
|
||||
--treee -t include syntax tree (disables --verify)
|
||||
--tree -t include syntax tree (disables --verify)
|
||||
|
||||
Extensions of generated files:
|
||||
'.pyc_dis' '.pyo_dis' successfully decompiled (and verified if --verify)
|
||||
+ '_unverified' successfully decompile but --verify failed
|
||||
+ '_failed' decompile failed (contact author for enhancement)
|
||||
"""
|
||||
|
||||
from __future__ import print_function
|
||||
import sys, os, getopt, time
|
||||
""" % ((program,) * 5)
|
||||
|
||||
program = os.path.basename(__file__)
|
||||
|
||||
from uncompyle6 import verify, check_python_version
|
||||
from uncompyle6.main import main, status_msg
|
||||
from uncompyle6.version import VERSION
|
||||
|
||||
def usage():
|
||||
print("""usage:
|
||||
%s [--help] [--verify] [--asm] [--tree] [--grammar] [-o <path>] FILE|DIR...
|
||||
""" % program)
|
||||
%s [--verify] [--asm] [--tree] [--grammar] [-o <path>] FILE|DIR...
|
||||
%s [--help | -h | --version | -V]
|
||||
""" % (program, program))
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
@@ -68,8 +74,8 @@ timestamp = False
|
||||
timestampfmt = "# %Y.%m.%d %H:%M:%S %Z"
|
||||
|
||||
try:
|
||||
opts, files = getopt.getopt(sys.argv[1:], 'hagtdro:c:p:',
|
||||
'help asm grammar recurse timestamp tree verify '
|
||||
opts, files = getopt.getopt(sys.argv[1:], 'hagtdrVo:c:p:',
|
||||
'help asm grammar recurse timestamp tree verify version '
|
||||
'showgrammar'.split(' '))
|
||||
except getopt.GetoptError as e:
|
||||
print('%s: %s' % (os.path.basename(sys.argv[0]), e), file=sys.stderr)
|
||||
@@ -80,6 +86,9 @@ for opt, val in opts:
|
||||
if opt in ('-h', '--help'):
|
||||
print(__doc__)
|
||||
sys.exit(0)
|
||||
elif opt in ('-V', '--version'):
|
||||
print("%s %s" % (program, VERSION))
|
||||
sys.exit(0)
|
||||
elif opt == '--verify':
|
||||
options['do_verify'] = True
|
||||
elif opt in ('--asm', '-a'):
|
||||
@@ -92,13 +101,13 @@ for opt, val in opts:
|
||||
options['showgrammar'] = True
|
||||
elif opt == '-o':
|
||||
outfile = val
|
||||
elif opt == ('--timestamp', '-d'):
|
||||
elif opt in ('--timestamp', '-d'):
|
||||
timestamp = True
|
||||
elif opt == '-c':
|
||||
codes.append(val)
|
||||
elif opt == '-p':
|
||||
numproc = int(val)
|
||||
elif opt == ('--recurse', '-r'):
|
||||
elif opt in ('--recurse', '-r'):
|
||||
recurse_dirs = True
|
||||
else:
|
||||
print(opt, file=sys.stderr)
|
||||
|
@@ -6,7 +6,8 @@ machine:
|
||||
|
||||
dependencies:
|
||||
override:
|
||||
- pip install -r test-requirements.txt
|
||||
- pip install -r requirements.txt
|
||||
- pip install -r requirements-dev.txt
|
||||
test:
|
||||
override:
|
||||
- python ./setup.py develop && make check-2.7
|
||||
|
21
pytest/test_single_compile.py
Normal file
21
pytest/test_single_compile.py
Normal file
@@ -0,0 +1,21 @@
|
||||
import pytest
|
||||
from uncompyle6 import PYTHON_VERSION, PYTHON3, deparse_code
|
||||
|
||||
def test_single_mode():
|
||||
single_expressions = (
|
||||
'i = 1',
|
||||
'i and (j or k)',
|
||||
'i += 1',
|
||||
'i = j % 4',
|
||||
'i = {}',
|
||||
'i = []',
|
||||
'while i < 1 or stop:\n i\n',
|
||||
'while i < 1 or stop:\n print%s\n' % ('(i)' if PYTHON3 else ' i'),
|
||||
'for i in range(10):\n i\n',
|
||||
'for i in range(10):\n for j in range(10):\n i + j\n',
|
||||
'try:\n i\nexcept Exception:\n j\nelse:\n k\n'
|
||||
)
|
||||
|
||||
for expr in single_expressions:
|
||||
code = compile(expr + '\n', '<string>', 'single')
|
||||
assert deparse_code(PYTHON_VERSION, code, compile_mode='single').text == expr + '\n'
|
1
requirements.txt
Normal file
1
requirements.txt
Normal file
@@ -0,0 +1 @@
|
||||
spark-parser >= 1.1.1
|
@@ -6,3 +6,6 @@ doc_files = README
|
||||
# USAGE.txt
|
||||
# doc/
|
||||
# examples/
|
||||
|
||||
[bdist_wheel]
|
||||
universal=1
|
||||
|
27
setup.py
27
setup.py
@@ -1,32 +1,25 @@
|
||||
#! python
|
||||
#!/usr/bin/env python
|
||||
|
||||
"""Setup script for the 'uncompyle6' distribution."""
|
||||
|
||||
from distutils.core import setup, Extension
|
||||
|
||||
# Get the package information used in setup().
|
||||
# from __pkginfo__ import \
|
||||
# author, author_email, classifiers, \
|
||||
# install_requires, license, long_description, \
|
||||
# modname, packages, py_modules, \
|
||||
# short_desc, version, web, zip_safe
|
||||
|
||||
from __pkginfo__ import \
|
||||
author, author_email, \
|
||||
long_description, \
|
||||
author, author_email, install_requires, \
|
||||
license, long_description, classifiers, \
|
||||
modname, packages, py_modules, scripts, \
|
||||
short_desc, version, web, zip_safe
|
||||
short_desc, web, zip_safe
|
||||
|
||||
__import__('pkg_resources')
|
||||
from setuptools import setup
|
||||
|
||||
exec(open('uncompyle6/version.py').read())
|
||||
|
||||
setup(
|
||||
author = author,
|
||||
author_email = author_email,
|
||||
# classifiers = classifiers,
|
||||
classifiers = classifiers,
|
||||
description = short_desc,
|
||||
# install_requires = install_requires,
|
||||
# license = license,
|
||||
install_requires = install_requires,
|
||||
license = license,
|
||||
long_description = long_description,
|
||||
py_modules = py_modules,
|
||||
name = modname,
|
||||
@@ -35,5 +28,5 @@ setup(
|
||||
url = web,
|
||||
setup_requires = ['nose>=1.0'],
|
||||
scripts = scripts,
|
||||
version = version,
|
||||
version = VERSION,
|
||||
zip_safe = zip_safe)
|
||||
|
@@ -1 +0,0 @@
|
||||
pytest
|
@@ -20,7 +20,11 @@ check:
|
||||
$(MAKE) check-$$PYTHON_VERSION
|
||||
|
||||
#: Run working tests from Python 2.6 or 2.7
|
||||
check-2.6 check-2.7: check-bytecode check-2.7-ok
|
||||
check-2.6 check-2.7: check-bytecode-sans-3.5 check-2.7-ok
|
||||
|
||||
#: Run working tests from Python 3.2
|
||||
check-3.2: check-bytecode
|
||||
$(PYTHON) test_pythonlib.py --bytecode-3.2 --verify $(COMPILE)
|
||||
|
||||
#: Run working tests from Python 3.3
|
||||
check-3.3: check-bytecode
|
||||
@@ -30,7 +34,8 @@ check-3.3: check-bytecode
|
||||
check-3.5: check-bytecode
|
||||
|
||||
#: Run working tests from Python 3.4
|
||||
check-3.4: check-bytecode check-2.7-ok
|
||||
check-3.4: check-bytecode check-3.4-ok check-2.7-ok
|
||||
$(PYTHON) test_pythonlib.py --bytecode-3.4 --verify $(COMPILE)
|
||||
|
||||
#: Check deparsing only, but from a different Python version
|
||||
check-disasm:
|
||||
@@ -42,6 +47,11 @@ check-bytecode-2:
|
||||
|
||||
#: Check deparsing bytecode only
|
||||
check-bytecode:
|
||||
$(PYTHON) test_pythonlib.py --bytecode-2.5 --bytecode-2.6 --bytecode-2.7 \
|
||||
--bytecode-3.2 --bytecode-3.3 --bytecode-3.4 --bytecode-3.5
|
||||
|
||||
#: Check deparsing bytecode only
|
||||
check-bytecode-sans-3.5:
|
||||
$(PYTHON) test_pythonlib.py --bytecode-2.5 --bytecode-2.6 --bytecode-2.7 \
|
||||
--bytecode-3.2 --bytecode-3.3 --bytecode-3.4
|
||||
|
||||
@@ -69,6 +79,10 @@ check-bytecode-3.3:
|
||||
check-bytecode-3.4:
|
||||
$(PYTHON) test_pythonlib.py --bytecode-3.4
|
||||
|
||||
#: Check deparsing Python 3.5
|
||||
check-bytecode-3.5:
|
||||
$(PYTHON) test_pythonlib.py --bytecode-3.5
|
||||
|
||||
#: short tests for bytecodes only for this version of Python
|
||||
check-native-short:
|
||||
$(PYTHON) test_pythonlib.py --bytecode-$(PYTHON_VERSION) --verify $(COMPILE)
|
||||
@@ -77,6 +91,14 @@ check-native-short:
|
||||
check-2.7-ok:
|
||||
$(PYTHON) test_pythonlib.py --ok-2.7 --verify $(COMPILE)
|
||||
|
||||
#: Run longer Python 3.2's lib files known to be okay
|
||||
check-3.2-ok:
|
||||
$(PYTHON) test_pythonlib.py --ok-3.2 --verify $(COMPILE)
|
||||
|
||||
#: Run longer Python 3.4's lib files known to be okay
|
||||
check-3.4-ok:
|
||||
$(PYTHON) test_pythonlib.py --ok-3.4 --verify $(COMPILE)
|
||||
|
||||
clean: clean-py-dis clean-dis clean-unverified
|
||||
|
||||
clean-dis:
|
||||
|
BIN
test/bytecode_2.5/10_if_else_ternary.pyc
Normal file
BIN
test/bytecode_2.5/10_if_else_ternary.pyc
Normal file
Binary file not shown.
BIN
test/bytecode_2.6/10_if_else_ternary.pyc
Normal file
BIN
test/bytecode_2.6/10_if_else_ternary.pyc
Normal file
Binary file not shown.
BIN
test/bytecode_2.7/05_long_list.pyc
Normal file
BIN
test/bytecode_2.7/05_long_list.pyc
Normal file
Binary file not shown.
BIN
test/bytecode_2.7/10_if_else_ternary.pyc
Normal file
BIN
test/bytecode_2.7/10_if_else_ternary.pyc
Normal file
Binary file not shown.
Binary file not shown.
BIN
test/bytecode_3.2/06_classbug.pyc
Normal file
BIN
test/bytecode_3.2/06_classbug.pyc
Normal file
Binary file not shown.
BIN
test/bytecode_3.4/05_const_map.pyc
Normal file
BIN
test/bytecode_3.4/05_const_map.pyc
Normal file
Binary file not shown.
Binary file not shown.
BIN
test/bytecode_3.4/05_with.pyc
Normal file
BIN
test/bytecode_3.4/05_with.pyc
Normal file
Binary file not shown.
BIN
test/bytecode_3.5/00_assign.pyc
Normal file
BIN
test/bytecode_3.5/00_assign.pyc
Normal file
Binary file not shown.
BIN
test/bytecode_3.5/00_import.pyc
Normal file
BIN
test/bytecode_3.5/00_import.pyc
Normal file
Binary file not shown.
BIN
test/bytecode_3.5/00_pass.pyc
Normal file
BIN
test/bytecode_3.5/00_pass.pyc
Normal file
Binary file not shown.
BIN
test/bytecode_3.5/01_boolean.pyc
Normal file
BIN
test/bytecode_3.5/01_boolean.pyc
Normal file
Binary file not shown.
BIN
test/bytecode_3.5/01_class.pyc
Normal file
BIN
test/bytecode_3.5/01_class.pyc
Normal file
Binary file not shown.
BIN
test/bytecode_3.5/01_fns.pyc
Normal file
BIN
test/bytecode_3.5/01_fns.pyc
Normal file
Binary file not shown.
BIN
test/bytecode_3.5/01_list_comprehension.pyc
Normal file
BIN
test/bytecode_3.5/01_list_comprehension.pyc
Normal file
Binary file not shown.
BIN
test/bytecode_3.5/01_positional.pyc
Normal file
BIN
test/bytecode_3.5/01_positional.pyc
Normal file
Binary file not shown.
BIN
test/bytecode_3.5/01_try_except.pyc
Normal file
BIN
test/bytecode_3.5/01_try_except.pyc
Normal file
Binary file not shown.
BIN
test/bytecode_3.5/02_closure.pyc
Normal file
BIN
test/bytecode_3.5/02_closure.pyc
Normal file
Binary file not shown.
BIN
test/bytecode_3.5/02_def.pyc
Normal file
BIN
test/bytecode_3.5/02_def.pyc
Normal file
Binary file not shown.
BIN
test/bytecode_3.5/02_slice.pyc
Normal file
BIN
test/bytecode_3.5/02_slice.pyc
Normal file
Binary file not shown.
BIN
test/bytecode_3.5/05_abc_class.pyc
Normal file
BIN
test/bytecode_3.5/05_abc_class.pyc
Normal file
Binary file not shown.
BIN
test/bytecode_3.5/05_class.pyc
Normal file
BIN
test/bytecode_3.5/05_class.pyc
Normal file
Binary file not shown.
BIN
test/bytecode_3.5/05_const_map.pyc
Normal file
BIN
test/bytecode_3.5/05_const_map.pyc
Normal file
Binary file not shown.
BIN
test/bytecode_3.5/05_if.pyc
Normal file
BIN
test/bytecode_3.5/05_if.pyc
Normal file
Binary file not shown.
BIN
test/bytecode_3.5/05_if_assign.pyc
Normal file
BIN
test/bytecode_3.5/05_if_assign.pyc
Normal file
Binary file not shown.
BIN
test/bytecode_3.5/05_ifelse.pyc
Normal file
BIN
test/bytecode_3.5/05_ifelse.pyc
Normal file
Binary file not shown.
BIN
test/bytecode_3.5/05_list_comprehension.pyc
Normal file
BIN
test/bytecode_3.5/05_list_comprehension.pyc
Normal file
Binary file not shown.
BIN
test/bytecode_3.5/05_long_list.pyc
Normal file
BIN
test/bytecode_3.5/05_long_list.pyc
Normal file
Binary file not shown.
BIN
test/bytecode_3.5/05_static_method.pyc
Normal file
BIN
test/bytecode_3.5/05_static_method.pyc
Normal file
Binary file not shown.
BIN
test/bytecode_3.5/05_try_except.pyc
Normal file
BIN
test/bytecode_3.5/05_try_except.pyc
Normal file
Binary file not shown.
BIN
test/bytecode_3.5/05_with.pyc
Normal file
BIN
test/bytecode_3.5/05_with.pyc
Normal file
Binary file not shown.
BIN
test/bytecode_3.5/06_classbug.pyc
Normal file
BIN
test/bytecode_3.5/06_classbug.pyc
Normal file
Binary file not shown.
BIN
test/bytecode_3.5/10_class.pyc
Normal file
BIN
test/bytecode_3.5/10_class.pyc
Normal file
Binary file not shown.
BIN
test/bytecode_3.5/10_del.pyc
Normal file
BIN
test/bytecode_3.5/10_del.pyc
Normal file
Binary file not shown.
BIN
test/bytecode_3.5/10_for.pyc
Normal file
BIN
test/bytecode_3.5/10_for.pyc
Normal file
Binary file not shown.
BIN
test/bytecode_3.5/10_keyword.pyc
Normal file
BIN
test/bytecode_3.5/10_keyword.pyc
Normal file
Binary file not shown.
BIN
test/bytecode_3.5/10_mixed_boolean.pyc
Normal file
BIN
test/bytecode_3.5/10_mixed_boolean.pyc
Normal file
Binary file not shown.
BIN
test/bytecode_3.5/10_while.pyc
Normal file
BIN
test/bytecode_3.5/10_while.pyc
Normal file
Binary file not shown.
BIN
test/bytecode_3.5/15_assert.pyc
Normal file
BIN
test/bytecode_3.5/15_assert.pyc
Normal file
Binary file not shown.
BIN
test/bytecode_3.5/15_for_if.pyc
Normal file
BIN
test/bytecode_3.5/15_for_if.pyc
Normal file
Binary file not shown.
BIN
test/bytecode_3.5/20_try_except.pyc
Normal file
BIN
test/bytecode_3.5/20_try_except.pyc
Normal file
Binary file not shown.
BIN
test/bytecode_3.5/25_try_except.pyc
Normal file
BIN
test/bytecode_3.5/25_try_except.pyc
Normal file
Binary file not shown.
@@ -70,7 +70,8 @@ for root, dirs, basenames in os.walk('simple_source'):
|
||||
simple_source.append(os.path.join(root, basename)[0:-3])
|
||||
pass
|
||||
|
||||
tests['2.6'] = tests['2.7'] = tests['3.2'] = tests['3.3'] = tests['3.4'] = simple_source
|
||||
tests['2.6'] = tests['2.7'] = tests['3.2'] = \
|
||||
tests['3.3'] = tests['3.4'] = tests['3.5'] = simple_source
|
||||
|
||||
total_tests = len(tests['2.7'])
|
||||
#tests['2.2'].sort(); print tests['2.2']
|
||||
|
BIN
test/ok_lib2.7/_abcoll.pyc
Normal file
BIN
test/ok_lib2.7/_abcoll.pyc
Normal file
Binary file not shown.
BIN
test/ok_lib2.7/_abcoll.pyo
Normal file
BIN
test/ok_lib2.7/_abcoll.pyo
Normal file
Binary file not shown.
Binary file not shown.
BIN
test/ok_lib2.7/antigravity.pyo
Normal file
BIN
test/ok_lib2.7/antigravity.pyo
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
test/ok_lib3.2/antigravity.cpython-32.pyc
Normal file
BIN
test/ok_lib3.2/antigravity.cpython-32.pyc
Normal file
Binary file not shown.
BIN
test/ok_lib3.2/antigravity.cpython-32.pyo
Normal file
BIN
test/ok_lib3.2/antigravity.cpython-32.pyo
Normal file
Binary file not shown.
17
test/ok_lib3.4/antigravity.py
Normal file
17
test/ok_lib3.4/antigravity.py
Normal file
@@ -0,0 +1,17 @@
|
||||
|
||||
import webbrowser
|
||||
import hashlib
|
||||
|
||||
webbrowser.open("http://xkcd.com/353/")
|
||||
|
||||
def geohash(latitude, longitude, datedow):
|
||||
'''Compute geohash() using the Munroe algorithm.
|
||||
|
||||
>>> geohash(37.421542, -122.085589, b'2005-05-26-10458.68')
|
||||
37.857713 -122.544543
|
||||
|
||||
'''
|
||||
# http://xkcd.com/426/
|
||||
h = hashlib.md5(datedow).hexdigest()
|
||||
p, q = [('%f' % float.fromhex('0.' + x)) for x in (h[:16], h[16:32])]
|
||||
print('%d%s %d%s' % (latitude, p[1:], longitude, q[1:]))
|
BIN
test/ok_lib3.4/antigravity.pyc
Normal file
BIN
test/ok_lib3.4/antigravity.pyc
Normal file
Binary file not shown.
92
test/ok_lib3.4/bisect.py
Normal file
92
test/ok_lib3.4/bisect.py
Normal file
@@ -0,0 +1,92 @@
|
||||
"""Bisection algorithms."""
|
||||
|
||||
def insort_right(a, x, lo=0, hi=None):
|
||||
"""Insert item x in list a, and keep it sorted assuming a is sorted.
|
||||
|
||||
If x is already in a, insert it to the right of the rightmost x.
|
||||
|
||||
Optional args lo (default 0) and hi (default len(a)) bound the
|
||||
slice of a to be searched.
|
||||
"""
|
||||
|
||||
if lo < 0:
|
||||
raise ValueError('lo must be non-negative')
|
||||
if hi is None:
|
||||
hi = len(a)
|
||||
while lo < hi:
|
||||
mid = (lo+hi)//2
|
||||
if x < a[mid]: hi = mid
|
||||
else: lo = mid+1
|
||||
a.insert(lo, x)
|
||||
|
||||
insort = insort_right # backward compatibility
|
||||
|
||||
def bisect_right(a, x, lo=0, hi=None):
|
||||
"""Return the index where to insert item x in list a, assuming a is sorted.
|
||||
|
||||
The return value i is such that all e in a[:i] have e <= x, and all e in
|
||||
a[i:] have e > x. So if x already appears in the list, a.insert(x) will
|
||||
insert just after the rightmost x already there.
|
||||
|
||||
Optional args lo (default 0) and hi (default len(a)) bound the
|
||||
slice of a to be searched.
|
||||
"""
|
||||
|
||||
if lo < 0:
|
||||
raise ValueError('lo must be non-negative')
|
||||
if hi is None:
|
||||
hi = len(a)
|
||||
while lo < hi:
|
||||
mid = (lo+hi)//2
|
||||
if x < a[mid]: hi = mid
|
||||
else: lo = mid+1
|
||||
return lo
|
||||
|
||||
bisect = bisect_right # backward compatibility
|
||||
|
||||
def insort_left(a, x, lo=0, hi=None):
|
||||
"""Insert item x in list a, and keep it sorted assuming a is sorted.
|
||||
|
||||
If x is already in a, insert it to the left of the leftmost x.
|
||||
|
||||
Optional args lo (default 0) and hi (default len(a)) bound the
|
||||
slice of a to be searched.
|
||||
"""
|
||||
|
||||
if lo < 0:
|
||||
raise ValueError('lo must be non-negative')
|
||||
if hi is None:
|
||||
hi = len(a)
|
||||
while lo < hi:
|
||||
mid = (lo+hi)//2
|
||||
if a[mid] < x: lo = mid+1
|
||||
else: hi = mid
|
||||
a.insert(lo, x)
|
||||
|
||||
|
||||
def bisect_left(a, x, lo=0, hi=None):
|
||||
"""Return the index where to insert item x in list a, assuming a is sorted.
|
||||
|
||||
The return value i is such that all e in a[:i] have e < x, and all e in
|
||||
a[i:] have e >= x. So if x already appears in the list, a.insert(x) will
|
||||
insert just before the leftmost x already there.
|
||||
|
||||
Optional args lo (default 0) and hi (default len(a)) bound the
|
||||
slice of a to be searched.
|
||||
"""
|
||||
|
||||
if lo < 0:
|
||||
raise ValueError('lo must be non-negative')
|
||||
if hi is None:
|
||||
hi = len(a)
|
||||
while lo < hi:
|
||||
mid = (lo+hi)//2
|
||||
if a[mid] < x: lo = mid+1
|
||||
else: hi = mid
|
||||
return lo
|
||||
|
||||
# Overwrite above definitions with a fast C implementation
|
||||
try:
|
||||
from _bisect import *
|
||||
except ImportError:
|
||||
pass
|
BIN
test/ok_lib3.4/bisect.pyc
Normal file
BIN
test/ok_lib3.4/bisect.pyc
Normal file
Binary file not shown.
11
test/simple_source/branching/10_if_else_ternary.py
Normal file
11
test/simple_source/branching/10_if_else_ternary.py
Normal file
@@ -0,0 +1,11 @@
|
||||
# Tests:
|
||||
|
||||
# ret_expr_or_cond ::= ret_expr
|
||||
# ret_cond ::= expr POP_JUMP_IF_FALSE expr RETURN_END_IF ret_expr_or_cond
|
||||
# ret_expr_or_cond ::= ret_cond
|
||||
# ret_or ::= expr JUMP_IF_TRUE_OR_POP ret_expr_or_cond COME_FROM
|
||||
|
||||
# See https://github.com/rocky/python-uncompyle6/issues/5
|
||||
|
||||
def minimize(x, y):
|
||||
return x or (x if x < y else y)
|
@@ -19,4 +19,4 @@
|
||||
# list_for ::= expr _for designator list_iter JUMP_BACK
|
||||
# list_iter ::= lc_body
|
||||
# lc_body ::= expr LIST_APPEND
|
||||
[ i * j for i in range(4) for j in range(7) ]
|
||||
# [ i * j for i in range(4) for j in range(7) ]
|
||||
|
19
test/simple_source/def/02_closure.py
Normal file
19
test/simple_source/def/02_closure.py
Normal file
@@ -0,0 +1,19 @@
|
||||
# Tests
|
||||
# Python3:
|
||||
# funcdef ::= mkfunc designator
|
||||
# designator ::= STORE_DEREF
|
||||
# mkfunc ::= load_closure BUILD_TUPLE_1 LOAD_CONST LOAD_CONST MAKE_CLOSURE_0
|
||||
# load_closure ::= LOAD_CLOSURE
|
||||
#
|
||||
# Python2:
|
||||
|
||||
# funcdef ::= mkfunc designator
|
||||
# designator ::= STORE_DEREF
|
||||
# mkfunc ::= load_closure LOAD_CONST MAKE_CLOSURE_0
|
||||
# load_closure ::= LOAD_CLOSURE
|
||||
|
||||
|
||||
def bug():
|
||||
def convert(node):
|
||||
return node and convert(node.left)
|
||||
return
|
14
test/simple_source/def/05_abc_class.py
Normal file
14
test/simple_source/def/05_abc_class.py
Normal file
@@ -0,0 +1,14 @@
|
||||
# Python3.5 bug from abc.py:
|
||||
# stmt ::= LOAD_CLOSURE RETURN_VALUE RETURN_LAST
|
||||
#
|
||||
# And this gets ignored.
|
||||
|
||||
# Note this is similar to 06_classbug.py but not the same.
|
||||
# classmethod -> object
|
||||
|
||||
class abstractclassmethod(classmethod):
|
||||
__isabstractmethod__ = True
|
||||
|
||||
def __init__(self, callable):
|
||||
callable.__isabstractmethod__ = True
|
||||
super().__init__(callable)
|
@@ -11,3 +11,7 @@
|
||||
import io
|
||||
class BZ2File(io.BufferedIOBase):
|
||||
pass
|
||||
|
||||
|
||||
class ABC(metaclass=BZ2File):
|
||||
pass
|
||||
|
16
test/simple_source/def/06_classbug.py
Normal file
16
test/simple_source/def/06_classbug.py
Normal file
@@ -0,0 +1,16 @@
|
||||
# Python 3.2 Bug from abc.py
|
||||
|
||||
# Make sure we handle:
|
||||
|
||||
# LOAD_FAST '__locals__'
|
||||
# STORE_LOCALS ''
|
||||
|
||||
# Note this is similar to 05_abc_class.py but not the same:
|
||||
# object -> classmethod
|
||||
|
||||
class abstractclassmethod(object):
|
||||
"""A Python 3.2 STORE_LOCALS bug
|
||||
"""
|
||||
|
||||
def __init__(self, callable):
|
||||
callable.__isabstractmethod__ = True
|
7
test/simple_source/expression/05_const_map.py
Normal file
7
test/simple_source/expression/05_const_map.py
Normal file
@@ -0,0 +1,7 @@
|
||||
# Addresses a bug in the way Python 3.5+ handles
|
||||
# creation of map constants
|
||||
opts = {'highlight': True,
|
||||
'start_line': -1,
|
||||
'end_line': None
|
||||
}
|
||||
print(opts)
|
3
test/simple_source/expression/05_long_list.py
Normal file
3
test/simple_source/expression/05_long_list.py
Normal file
@@ -0,0 +1,3 @@
|
||||
# Long lists pose a slowdown in uncompiling.
|
||||
x = [1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1]
|
||||
print(x)
|
2
test/simple_source/stmts/05_with.py
Normal file
2
test/simple_source/stmts/05_with.py
Normal file
@@ -0,0 +1,2 @@
|
||||
with (sys) as f:
|
||||
print(f)
|
@@ -55,22 +55,31 @@ PYO = ('*.pyo', )
|
||||
PYOC = ('*.pyc', '*.pyo')
|
||||
|
||||
test_options = {
|
||||
# name: (src_basedir, pattern, output_base_suffix, pythoin_version)
|
||||
# name: (src_basedir, pattern, output_base_suffix, python_version)
|
||||
'test':
|
||||
('test', PYC, 'test'),
|
||||
|
||||
'ok-2.6':
|
||||
(os.path.join(src_dir, 'ok_2.6'),
|
||||
PYC, 'ok-2.6', 2.6),
|
||||
PYOC, 'ok-2.6', 2.6),
|
||||
|
||||
'ok-2.7': (os.path.join(src_dir, 'ok_lib2.7'),
|
||||
PYC, 'ok-2.7', 2.7),
|
||||
PYOC, 'ok-2.7', 2.7),
|
||||
|
||||
'ok-3.2': (os.path.join(src_dir, 'ok_lib3.2'),
|
||||
PYOC, 'ok-3.2', 3.5),
|
||||
|
||||
'base-2.7': (os.path.join(src_dir, 'base_tests', 'python2.7'),
|
||||
PYC, 'base_2.7', 2.7),
|
||||
PYOC, 'base_2.7', 2.7),
|
||||
}
|
||||
|
||||
for vers in (2.5, 2.6, 2.7, 3.2, 3.3, 3.4):
|
||||
for vers in (2.7, 3.4, 3.5):
|
||||
pythonlib = "ok_lib%s" % vers
|
||||
key = "ok-%s" % vers
|
||||
test_options[key] = (os.path.join(src_dir, pythonlib), PYOC, key, vers)
|
||||
pass
|
||||
|
||||
for vers in (2.5, 2.6, 2.7, 3.2, 3.3, 3.4, 3.5):
|
||||
bytecode = "bytecode_%s" % vers
|
||||
key = "bytecode-%s" % vers
|
||||
test_options[key] = (bytecode, PYC, bytecode, vers)
|
||||
@@ -78,7 +87,7 @@ for vers in (2.5, 2.6, 2.7, 3.2, 3.3, 3.4):
|
||||
pythonlib = "python%s" % vers
|
||||
if vers >= 3.0:
|
||||
pythonlib = os.path.join(pythonlib, '__pycache__')
|
||||
test_options[key] = (os.path.join(lib_prefix, pythonlib), PYC, pythonlib, vers)
|
||||
test_options[key] = (os.path.join(lib_prefix, pythonlib), PYOC, pythonlib, vers)
|
||||
|
||||
#-----
|
||||
|
||||
@@ -93,7 +102,6 @@ def help():
|
||||
|
||||
# decompile and verify known good python 2.7
|
||||
test_pythonlib.py --ok-2.7 --verify
|
||||
|
||||
""")
|
||||
sys.exit(1)
|
||||
|
||||
|
@@ -30,13 +30,15 @@ from __future__ import print_function
|
||||
|
||||
import sys
|
||||
|
||||
__docformat__ = 'restructuredtext'
|
||||
|
||||
PYTHON3 = (sys.version_info >= (3, 0))
|
||||
|
||||
# We do this crazy way to support Python 2.6 which
|
||||
# doesn't support version_major, and has a bug in
|
||||
# floating point so we can't divide 26 by 10 and get
|
||||
# 2.6
|
||||
PYTHON_VERSION = sys.version_info[0]+ (sys.version_info[1] / 10.0)
|
||||
PYTHON_VERSION = sys.version_info[0] + (sys.version_info[1] / 10.0)
|
||||
PYTHON_VERSION_STR = "%s.%s" % (sys.version_info[0], sys.version_info[1])
|
||||
|
||||
sys.setrecursionlimit(5000)
|
||||
@@ -50,6 +52,11 @@ def check_python_version(program):
|
||||
|
||||
import uncompyle6.semantics.pysource
|
||||
import uncompyle6.semantics.fragments
|
||||
import uncompyle6.load
|
||||
|
||||
# Export some functions
|
||||
from uncompyle6.load import load_module, load_file
|
||||
from uncompyle6.main import uncompyle_file
|
||||
|
||||
# Conventience functions so you can say:
|
||||
# from uncompyle6 import deparse_code
|
||||
|
@@ -1,5 +1,5 @@
|
||||
# Copyright (c) 2000 by hartmut Goebel <h.goebel@crazy-compilers.com>
|
||||
# Copyright (c) 2015 by Rocky Bernstein
|
||||
# Copyright (c) 2000 by hartmut Goebel <h.goebel@crazy-compilers.com>
|
||||
from __future__ import print_function
|
||||
|
||||
import imp, marshal, os, py_compile, sys, tempfile
|
||||
@@ -26,7 +26,7 @@ def check_object_path(path):
|
||||
spath = path if PYTHON3 else path.decode('utf-8')
|
||||
path = tempfile.mkstemp(prefix=basename + '-',
|
||||
suffix='.pyc', text=False)[1]
|
||||
py_compile.compile(spath, cfile=path)
|
||||
py_compile.compile(spath, cfile=path, doraise=True)
|
||||
|
||||
if not path.endswith(".pyc") and not path.endswith(".pyo"):
|
||||
raise ValueError("path %s must point to a .py or .pyc file\n" %
|
||||
|
@@ -1,5 +1,5 @@
|
||||
from __future__ import print_function
|
||||
import datetime, inspect, os, sys
|
||||
import datetime, os, sys
|
||||
|
||||
from uncompyle6 import verify, PYTHON_VERSION
|
||||
from uncompyle6.code import iscode
|
||||
@@ -57,9 +57,10 @@ def uncompyle_file(filename, outstream=None, showasm=False, showast=False,
|
||||
timestamp, showgrammar, code_objects=code_objects)
|
||||
co = None
|
||||
|
||||
# FIXME: combine into an options parameter
|
||||
def main(in_base, out_base, files, codes, outfile=None,
|
||||
showasm=False, showast=False, do_verify=False,
|
||||
showgrammar=False):
|
||||
showgrammar=False, raise_on_error=False):
|
||||
"""
|
||||
in_base base directory for input files
|
||||
out_base base directory for output files (ignored when
|
||||
@@ -108,7 +109,7 @@ def main(in_base, out_base, files, codes, outfile=None,
|
||||
try:
|
||||
uncompyle_file(infile, outstream, showasm, showast, showgrammar)
|
||||
tot_files += 1
|
||||
except ValueError as e:
|
||||
except (ValueError, SyntaxError) as e:
|
||||
sys.stderr.write("\n# %s" % e)
|
||||
failed_files += 1
|
||||
except KeyboardInterrupt:
|
||||
@@ -117,14 +118,14 @@ def main(in_base, out_base, files, codes, outfile=None,
|
||||
os.remove(outfile)
|
||||
sys.stderr.write("\nLast file: %s " % (infile))
|
||||
raise
|
||||
except:
|
||||
failed_files += 1
|
||||
if outfile:
|
||||
outstream.close()
|
||||
os.rename(outfile, outfile + '_failed')
|
||||
else:
|
||||
sys.stderr.write("\n# %s" % sys.exc_info()[1])
|
||||
sys.stderr.write("\n# Can't uncompile %s\n" % infile)
|
||||
# except:
|
||||
# failed_files += 1
|
||||
# if outfile:
|
||||
# outstream.close()
|
||||
# os.rename(outfile, outfile + '_failed')
|
||||
# else:
|
||||
# sys.stderr.write("\n# %s" % sys.exc_info()[1])
|
||||
# sys.stderr.write("\n# Can't uncompile %s\n" % infile)
|
||||
else: # uncompile successful
|
||||
if outfile:
|
||||
outstream.close()
|
||||
@@ -143,6 +144,8 @@ def main(in_base, out_base, files, codes, outfile=None,
|
||||
if not outfile:
|
||||
print("### Error Verifiying %s" % filename, file=sys.stderr)
|
||||
print(e, file=sys.stderr)
|
||||
if raise_on_error:
|
||||
raise
|
||||
pass
|
||||
pass
|
||||
pass
|
||||
|
@@ -18,7 +18,6 @@ from __future__ import print_function
|
||||
import sys, types
|
||||
from struct import unpack
|
||||
|
||||
import uncompyle6.scanners.scanner3 as scan3
|
||||
from uncompyle6.magics import PYTHON_MAGIC_INT
|
||||
from uncompyle6.code import Code3
|
||||
|
||||
|
@@ -7,6 +7,8 @@ This is a superset of Python 2.3's opcode.py with some opcodes that simplify
|
||||
parsing and semantic interpretation.
|
||||
"""
|
||||
|
||||
# FIXME: DRY this along the lines of opcode_3x.
|
||||
|
||||
cmp_op = ('<', '<=', '==', '!=', '>', '>=', 'in', 'not in', 'is',
|
||||
'is not', 'exception match', 'BAD')
|
||||
|
||||
|
@@ -7,6 +7,8 @@ This is a superset of Python 2.5's opcode.py with some opcodes that simplify
|
||||
parsing and semantic interpretation.
|
||||
"""
|
||||
|
||||
# FIXME: DRY this along the lines of opcode_3x.
|
||||
|
||||
cmp_op = ('<', '<=', '==', '!=', '>', '>=', 'in', 'not in', 'is',
|
||||
'is not', 'exception match', 'BAD')
|
||||
|
||||
|
@@ -7,6 +7,8 @@ This is a superset of Python 3.4's opcode.py with some opcodes that simplify
|
||||
parsing and semantic interpretation.
|
||||
"""
|
||||
|
||||
# FIXME: DRY this along the lines of opcode_3x.
|
||||
|
||||
cmp_op = ('<', '<=', '==', '!=', '>', '>=', 'in', 'not in', 'is',
|
||||
'is not', 'exception match', 'BAD')
|
||||
|
||||
|
@@ -7,6 +7,8 @@ This is a superset of Python 3.4's opcode.py with some opcodes that simplify
|
||||
parsing and semantic interpretation.
|
||||
"""
|
||||
|
||||
# FIXME: DRY this along the lines of opcode_3x.
|
||||
|
||||
cmp_op = ('<', '<=', '==', '!=', '>', '>=', 'in', 'not in', 'is',
|
||||
'is not', 'exception match', 'BAD')
|
||||
|
||||
|
@@ -3,42 +3,27 @@ CPython 3.2 bytecode opcodes
|
||||
|
||||
This is used in scanner (bytecode disassembly) and parser (Python grammar).
|
||||
|
||||
This is a superset of Python 3.4's opcode.py with some opcodes that simplify
|
||||
This is a superset of Python 3.2's opcode.py with some opcodes that simplify
|
||||
parsing and semantic interpretation.
|
||||
"""
|
||||
|
||||
cmp_op = ('<', '<=', '==', '!=', '>', '>=', 'in', 'not in', 'is',
|
||||
'is not', 'exception match', 'BAD')
|
||||
from copy import deepcopy
|
||||
|
||||
hasconst = []
|
||||
hasname = []
|
||||
hasjrel = []
|
||||
hasjabs = []
|
||||
haslocal = []
|
||||
hascompare = []
|
||||
hasfree = []
|
||||
hasnargs = []
|
||||
import uncompyle6.opcodes.opcode_3x as opcode_3x
|
||||
from uncompyle6.opcodes.opcode_3x import fields2copy
|
||||
|
||||
# FIXME: can we DRY this even more?
|
||||
|
||||
opmap = {}
|
||||
opname = [''] * 256
|
||||
for op in range(256): opname[op] = '<%r>' % (op,)
|
||||
del op
|
||||
hasjrel = []
|
||||
hasjabs = []
|
||||
|
||||
def def_op(name, op):
|
||||
opname[op] = name
|
||||
opmap[name] = op
|
||||
for object in fields2copy:
|
||||
globals()[object] = deepcopy(getattr(opcode_3x, object))
|
||||
|
||||
def name_op(name, op):
|
||||
def_op(name, op)
|
||||
hasname.append(op)
|
||||
|
||||
def jrel_op(name, op):
|
||||
def_op(name, op)
|
||||
hasjrel.append(op)
|
||||
|
||||
def jabs_op(name, op):
|
||||
def_op(name, op)
|
||||
hasjabs.append(op)
|
||||
# There are no opcodes to add or change.
|
||||
# If there were, they'd be listed below.
|
||||
|
||||
def updateGlobal():
|
||||
# JUMP_OPs are used in verification are set in the scanner
|
||||
@@ -50,165 +35,14 @@ def updateGlobal():
|
||||
globals().update(dict([(k.replace('+', '_'), v) for (k, v) in opmap.items()]))
|
||||
globals().update({'JUMP_OPs': map(lambda op: opname[op], hasjrel + hasjabs)})
|
||||
|
||||
# Instruction opcodes for compiled code
|
||||
# Blank lines correspond to available opcodes
|
||||
|
||||
def_op('STOP_CODE', 0)
|
||||
def_op('POP_TOP', 1)
|
||||
def_op('ROT_TWO', 2)
|
||||
def_op('ROT_THREE', 3)
|
||||
def_op('DUP_TOP', 4)
|
||||
def_op('DUP_TOP_TWO', 5)
|
||||
|
||||
def_op('NOP', 9)
|
||||
def_op('UNARY_POSITIVE', 10)
|
||||
def_op('UNARY_NEGATIVE', 11)
|
||||
def_op('UNARY_NOT', 12)
|
||||
|
||||
def_op('UNARY_INVERT', 15)
|
||||
|
||||
def_op('BINARY_POWER', 19)
|
||||
def_op('BINARY_MULTIPLY', 20)
|
||||
|
||||
def_op('BINARY_MODULO', 22)
|
||||
def_op('BINARY_ADD', 23)
|
||||
def_op('BINARY_SUBTRACT', 24)
|
||||
def_op('BINARY_SUBSCR', 25)
|
||||
def_op('BINARY_FLOOR_DIVIDE', 26)
|
||||
def_op('BINARY_TRUE_DIVIDE', 27)
|
||||
def_op('INPLACE_FLOOR_DIVIDE', 28)
|
||||
def_op('INPLACE_TRUE_DIVIDE', 29)
|
||||
|
||||
# Gone from Python 3 are Python2's
|
||||
# SLICE+0 .. SLICE+3
|
||||
# STORE_SLICE+0 .. STORE_SLICE+3
|
||||
# DELETE_SLICE+0 .. DELETE_SLICE+3
|
||||
|
||||
def_op('STORE_MAP', 54)
|
||||
def_op('INPLACE_ADD', 55)
|
||||
def_op('INPLACE_SUBTRACT', 56)
|
||||
def_op('INPLACE_MULTIPLY', 57)
|
||||
|
||||
def_op('INPLACE_MODULO', 59)
|
||||
def_op('STORE_SUBSCR', 60)
|
||||
def_op('DELETE_SUBSCR', 61)
|
||||
def_op('BINARY_LSHIFT', 62)
|
||||
def_op('BINARY_RSHIFT', 63)
|
||||
def_op('BINARY_AND', 64)
|
||||
def_op('BINARY_XOR', 65)
|
||||
def_op('BINARY_OR', 66)
|
||||
def_op('INPLACE_POWER', 67)
|
||||
def_op('GET_ITER', 68)
|
||||
def_op('STORE_LOCALS', 69)
|
||||
|
||||
def_op('PRINT_EXPR', 70)
|
||||
def_op('LOAD_BUILD_CLASS', 71)
|
||||
|
||||
# Python3 drops/changes:
|
||||
# def_op('PRINT_ITEM', 71)
|
||||
# def_op('PRINT_NEWLINE', 72)
|
||||
# def_op('PRINT_ITEM_TO', 73)
|
||||
# def_op('PRINT_NEWLINE_TO', 74)
|
||||
|
||||
def_op('INPLACE_LSHIFT', 75)
|
||||
def_op('INPLACE_RSHIFT', 76)
|
||||
def_op('INPLACE_AND', 77)
|
||||
def_op('INPLACE_XOR', 78)
|
||||
def_op('INPLACE_OR', 79)
|
||||
def_op('BREAK_LOOP', 80)
|
||||
def_op('WITH_CLEANUP', 81)
|
||||
|
||||
def_op('RETURN_VALUE', 83)
|
||||
def_op('IMPORT_STAR', 84)
|
||||
|
||||
def_op('YIELD_VALUE', 86)
|
||||
def_op('POP_BLOCK', 87)
|
||||
def_op('END_FINALLY', 88)
|
||||
def_op('POP_EXCEPT', 89)
|
||||
|
||||
HAVE_ARGUMENT = 90 # Opcodes from here have an argument:
|
||||
|
||||
name_op('STORE_NAME', 90) # Index in name list
|
||||
name_op('DELETE_NAME', 91) # ""
|
||||
def_op('UNPACK_SEQUENCE', 92) # Number of tuple items
|
||||
jrel_op('FOR_ITER', 93)
|
||||
def_op('UNPACK_EX', 94)
|
||||
name_op('STORE_ATTR', 95) # Index in name list
|
||||
name_op('DELETE_ATTR', 96) # ""
|
||||
name_op('STORE_GLOBAL', 97) # ""
|
||||
name_op('DELETE_GLOBAL', 98) # ""
|
||||
|
||||
# Python 2's DUP_TOPX is gone
|
||||
|
||||
def_op('LOAD_CONST', 100) # Index in const list
|
||||
hasconst.append(100)
|
||||
name_op('LOAD_NAME', 101) # Index in name list
|
||||
def_op('BUILD_TUPLE', 102) # Number of tuple items
|
||||
def_op('BUILD_LIST', 103) # Number of list items
|
||||
def_op('BUILD_SET', 104) # Number of set items
|
||||
def_op('BUILD_MAP', 105) # Number of dict entries (upto 255)
|
||||
name_op('LOAD_ATTR', 106) # Index in name list
|
||||
def_op('COMPARE_OP', 107) # Comparison operator
|
||||
hascompare.append(107)
|
||||
name_op('IMPORT_NAME', 108) # Index in name list
|
||||
name_op('IMPORT_FROM', 109) # Index in name list
|
||||
|
||||
jrel_op('JUMP_FORWARD', 110) # Number of bytes to skip
|
||||
jabs_op('JUMP_IF_FALSE_OR_POP', 111) # Target byte offset from beginning of code
|
||||
jabs_op('JUMP_IF_TRUE_OR_POP', 112) # ""
|
||||
jabs_op('JUMP_ABSOLUTE', 113) # ""
|
||||
jabs_op('POP_JUMP_IF_FALSE', 114) # ""
|
||||
jabs_op('POP_JUMP_IF_TRUE', 115) # ""
|
||||
|
||||
name_op('LOAD_GLOBAL', 116) # Index in name list
|
||||
|
||||
jabs_op('CONTINUE_LOOP', 119) # Target address
|
||||
jrel_op('SETUP_LOOP', 120) # Distance to target address
|
||||
jrel_op('SETUP_EXCEPT', 121) # ""
|
||||
jrel_op('SETUP_FINALLY', 122) # ""
|
||||
|
||||
def_op('LOAD_FAST', 124) # Local variable number
|
||||
haslocal.append(124)
|
||||
def_op('STORE_FAST', 125) # Local variable number
|
||||
haslocal.append(125)
|
||||
def_op('DELETE_FAST', 126) # Local variable number
|
||||
haslocal.append(126)
|
||||
|
||||
def_op('RAISE_VARARGS', 130) # Number of raise arguments (1, 2, or 3)
|
||||
def_op('CALL_FUNCTION', 131) # #args + (#kwargs << 8)
|
||||
hasnargs.append(131)
|
||||
def_op('MAKE_FUNCTION', 132) # Number of args with default values
|
||||
def_op('BUILD_SLICE', 133) # Number of items
|
||||
def_op('MAKE_CLOSURE', 134)
|
||||
def_op('LOAD_CLOSURE', 135)
|
||||
hasfree.append(135)
|
||||
def_op('LOAD_DEREF', 136)
|
||||
hasfree.append(136)
|
||||
def_op('STORE_DEREF', 137)
|
||||
hasfree.append(137)
|
||||
def_op('DELETE_DEREF', 138)
|
||||
hasfree.append(138)
|
||||
|
||||
def_op('CALL_FUNCTION_VAR', 140) # #args + (#kwargs << 8)
|
||||
hasnargs.append(140)
|
||||
def_op('CALL_FUNCTION_KW', 141) # #args + (#kwargs << 8)
|
||||
hasnargs.append(141)
|
||||
def_op('CALL_FUNCTION_VAR_KW', 142) # #args + (#kwargs << 8)
|
||||
hasnargs.append(142)
|
||||
|
||||
jrel_op('SETUP_WITH', 143)
|
||||
|
||||
def_op('LIST_APPEND', 145)
|
||||
def_op('SET_ADD', 146)
|
||||
def_op('MAP_ADD', 147)
|
||||
|
||||
def_op('EXTENDED_ARG', 144)
|
||||
EXTENDED_ARG = 144
|
||||
|
||||
updateGlobal()
|
||||
del def_op, name_op, jrel_op, jabs_op
|
||||
|
||||
from uncompyle6 import PYTHON_VERSION
|
||||
if PYTHON_VERSION == 3.2:
|
||||
import dis
|
||||
# for item in dis.opmap.items():
|
||||
# if item not in opmap.items():
|
||||
# print(item)
|
||||
assert all(item in opmap.items() for item in dis.opmap.items())
|
||||
|
||||
# opcode_3x.dump_opcodes(opmap)
|
||||
|
@@ -7,37 +7,31 @@ This is a superset of Python 3.3's opcode.py with some opcodes that simplify
|
||||
parsing and semantic interpretation.
|
||||
"""
|
||||
|
||||
cmp_op = ('<', '<=', '==', '!=', '>', '>=', 'in', 'not in', 'is',
|
||||
'is not', 'exception match', 'BAD')
|
||||
from copy import deepcopy
|
||||
|
||||
hasconst = []
|
||||
hasname = []
|
||||
hasjrel = []
|
||||
hasjabs = []
|
||||
haslocal = []
|
||||
hascompare = []
|
||||
hasfree = []
|
||||
import uncompyle6.opcodes.opcode_3x as opcode_3x
|
||||
from uncompyle6.opcodes.opcode_3x import fields2copy, rm_op
|
||||
|
||||
# FIXME: can we DRY this even more?
|
||||
|
||||
opmap = {}
|
||||
opname = [''] * 256
|
||||
for op in range(256): opname[op] = '<%r>' % (op,)
|
||||
del op
|
||||
hasconst = []
|
||||
hasjrel = []
|
||||
hasjabs = []
|
||||
|
||||
def def_op(name, op):
|
||||
opname[op] = name
|
||||
opmap[name] = op
|
||||
|
||||
def name_op(name, op):
|
||||
def_op(name, op)
|
||||
hasname.append(op)
|
||||
for object in fields2copy:
|
||||
globals()[object] = deepcopy(getattr(opcode_3x, object))
|
||||
|
||||
def jrel_op(name, op):
|
||||
def_op(name, op)
|
||||
hasjrel.append(op)
|
||||
# Below are opcodes since Python 3.2
|
||||
|
||||
def jabs_op(name, op):
|
||||
def_op(name, op)
|
||||
hasjabs.append(op)
|
||||
rm_op(opname, opmap, 'STOP_CODE', 0)
|
||||
|
||||
def_op('YIELD_FROM', 72)
|
||||
|
||||
def updateGlobal():
|
||||
# JUMP_OPs are used in verification are set in the scanner
|
||||
@@ -49,156 +43,9 @@ def updateGlobal():
|
||||
globals().update(dict([(k.replace('+', '_'), v) for (k, v) in opmap.items()]))
|
||||
globals().update({'JUMP_OPs': map(lambda op: opname[op], hasjrel + hasjabs)})
|
||||
|
||||
# Instruction opcodes for compiled code
|
||||
# Blank lines correspond to available opcodes
|
||||
|
||||
def_op('STOP_CODE', 0)
|
||||
def_op('POP_TOP', 1)
|
||||
def_op('ROT_TWO', 2)
|
||||
def_op('ROT_THREE', 3)
|
||||
def_op('DUP_TOP', 4)
|
||||
def_op('DUP_TOP_TWO', 5)
|
||||
|
||||
def_op('NOP', 9)
|
||||
def_op('UNARY_POSITIVE', 10)
|
||||
def_op('UNARY_NEGATIVE', 11)
|
||||
def_op('UNARY_NOT', 12)
|
||||
|
||||
def_op('UNARY_INVERT', 15)
|
||||
|
||||
def_op('BINARY_POWER', 19)
|
||||
def_op('BINARY_MULTIPLY', 20)
|
||||
|
||||
def_op('BINARY_MODULO', 22)
|
||||
def_op('BINARY_ADD', 23)
|
||||
def_op('BINARY_SUBTRACT', 24)
|
||||
def_op('BINARY_SUBSCR', 25)
|
||||
def_op('BINARY_FLOOR_DIVIDE', 26)
|
||||
def_op('BINARY_TRUE_DIVIDE', 27)
|
||||
def_op('INPLACE_FLOOR_DIVIDE', 28)
|
||||
def_op('INPLACE_TRUE_DIVIDE', 29)
|
||||
|
||||
# Gone from Python 3 are
|
||||
# Python 2's SLICE+0 .. SLICE+3
|
||||
|
||||
def_op('STORE_MAP', 54)
|
||||
def_op('INPLACE_ADD', 55)
|
||||
def_op('INPLACE_SUBTRACT', 56)
|
||||
def_op('INPLACE_MULTIPLY', 57)
|
||||
|
||||
def_op('INPLACE_MODULO', 59)
|
||||
def_op('STORE_SUBSCR', 60)
|
||||
def_op('DELETE_SUBSCR', 61)
|
||||
def_op('BINARY_LSHIFT', 62)
|
||||
def_op('BINARY_RSHIFT', 63)
|
||||
def_op('BINARY_AND', 64)
|
||||
def_op('BINARY_XOR', 65)
|
||||
def_op('BINARY_OR', 66)
|
||||
def_op('INPLACE_POWER', 67)
|
||||
def_op('GET_ITER', 68)
|
||||
def_op('STORE_LOCALS', 69)
|
||||
|
||||
def_op('PRINT_EXPR', 70)
|
||||
def_op('LOAD_BUILD_CLASS', 71)
|
||||
|
||||
# Python3 drops/changes:
|
||||
# def_op('PRINT_ITEM', 71)
|
||||
# def_op('PRINT_NEWLINE', 72)
|
||||
def_op('YIELD_FROM', 72)
|
||||
# def_op('PRINT_ITEM_TO', 73)
|
||||
# def_op('PRINT_NEWLINE_TO', 74)
|
||||
|
||||
def_op('INPLACE_LSHIFT', 75)
|
||||
def_op('INPLACE_RSHIFT', 76)
|
||||
def_op('INPLACE_AND', 77)
|
||||
def_op('INPLACE_XOR', 78)
|
||||
def_op('INPLACE_OR', 79)
|
||||
def_op('BREAK_LOOP', 80)
|
||||
def_op('WITH_CLEANUP', 81)
|
||||
|
||||
def_op('RETURN_VALUE', 83)
|
||||
def_op('IMPORT_STAR', 84)
|
||||
|
||||
def_op('YIELD_VALUE', 86)
|
||||
def_op('POP_BLOCK', 87)
|
||||
def_op('END_FINALLY', 88)
|
||||
def_op('POP_EXCEPT', 89)
|
||||
|
||||
HAVE_ARGUMENT = 90 # Opcodes from here have an argument:
|
||||
|
||||
name_op('STORE_NAME', 90) # Index in name list
|
||||
name_op('DELETE_NAME', 91) # ""
|
||||
def_op('UNPACK_SEQUENCE', 92) # Number of tuple items
|
||||
jrel_op('FOR_ITER', 93)
|
||||
def_op('UNPACK_EX', 94)
|
||||
name_op('STORE_ATTR', 95) # Index in name list
|
||||
name_op('DELETE_ATTR', 96) # ""
|
||||
name_op('STORE_GLOBAL', 97) # ""
|
||||
name_op('DELETE_GLOBAL', 98) # ""
|
||||
def_op('LOAD_CONST', 100) # Index in const list
|
||||
hasconst.append(100)
|
||||
name_op('LOAD_NAME', 101) # Index in name list
|
||||
def_op('BUILD_TUPLE', 102) # Number of tuple items
|
||||
def_op('BUILD_LIST', 103) # Number of list items
|
||||
def_op('BUILD_SET', 104) # Number of set items
|
||||
def_op('BUILD_MAP', 105) # Number of dict entries (upto 255)
|
||||
name_op('LOAD_ATTR', 106) # Index in name list
|
||||
def_op('COMPARE_OP', 107) # Comparison operator
|
||||
hascompare.append(107)
|
||||
name_op('IMPORT_NAME', 108) # Index in name list
|
||||
name_op('IMPORT_FROM', 109) # Index in name list
|
||||
|
||||
jrel_op('JUMP_FORWARD', 110) # Number of bytes to skip
|
||||
jabs_op('JUMP_IF_FALSE_OR_POP', 111) # Target byte offset from beginning of code
|
||||
jabs_op('JUMP_IF_TRUE_OR_POP', 112) # ""
|
||||
jabs_op('JUMP_ABSOLUTE', 113) # ""
|
||||
jabs_op('POP_JUMP_IF_FALSE', 114) # ""
|
||||
jabs_op('POP_JUMP_IF_TRUE', 115) # ""
|
||||
|
||||
name_op('LOAD_GLOBAL', 116) # Index in name list
|
||||
|
||||
jabs_op('CONTINUE_LOOP', 119) # Target address
|
||||
jrel_op('SETUP_LOOP', 120) # Distance to target address
|
||||
jrel_op('SETUP_EXCEPT', 121) # ""
|
||||
jrel_op('SETUP_FINALLY', 122) # ""
|
||||
|
||||
def_op('LOAD_FAST', 124) # Local variable number
|
||||
haslocal.append(124)
|
||||
def_op('STORE_FAST', 125) # Local variable number
|
||||
haslocal.append(125)
|
||||
def_op('DELETE_FAST', 126) # Local variable number
|
||||
haslocal.append(126)
|
||||
|
||||
def_op('RAISE_VARARGS', 130) # Number of raise arguments (1, 2, or 3)
|
||||
def_op('CALL_FUNCTION', 131) # #args + (#kwargs << 8)
|
||||
def_op('MAKE_FUNCTION', 132) # Number of args with default values
|
||||
def_op('BUILD_SLICE', 133) # Number of items
|
||||
def_op('MAKE_CLOSURE', 134)
|
||||
def_op('LOAD_CLOSURE', 135)
|
||||
hasfree.append(135)
|
||||
def_op('LOAD_DEREF', 136)
|
||||
hasfree.append(136)
|
||||
def_op('STORE_DEREF', 137)
|
||||
hasfree.append(137)
|
||||
def_op('DELETE_DEREF', 138)
|
||||
hasfree.append(138)
|
||||
|
||||
def_op('CALL_FUNCTION_VAR', 140) # #args + (#kwargs << 8)
|
||||
def_op('CALL_FUNCTION_KW', 141) # #args + (#kwargs << 8)
|
||||
def_op('CALL_FUNCTION_VAR_KW', 142) # #args + (#kwargs << 8)
|
||||
|
||||
jrel_op('SETUP_WITH', 143)
|
||||
|
||||
def_op('LIST_APPEND', 145)
|
||||
def_op('SET_ADD', 146)
|
||||
def_op('MAP_ADD', 147)
|
||||
|
||||
def_op('EXTENDED_ARG', 144)
|
||||
EXTENDED_ARG = 144
|
||||
|
||||
updateGlobal()
|
||||
del def_op, name_op, jrel_op, jabs_op
|
||||
|
||||
# FIXME: turn into pytest test
|
||||
from uncompyle6 import PYTHON_VERSION
|
||||
if PYTHON_VERSION == 3.3:
|
||||
import dis
|
||||
@@ -206,3 +53,5 @@ if PYTHON_VERSION == 3.3:
|
||||
# if item not in opmap.items():
|
||||
# print(item)
|
||||
assert all(item in opmap.items() for item in dis.opmap.items())
|
||||
|
||||
# opcode3x.dump_opcodes(opmap)
|
||||
|
@@ -1,44 +1,41 @@
|
||||
"""
|
||||
CPython 3.4 bytecode opcodes
|
||||
|
||||
This is used in scanner (bytecode disassembly) and parser (Python grammar).
|
||||
used in scanner (bytecode disassembly) and parser (Python grammar)
|
||||
|
||||
This is a superset of Python 3.4's opcode.py with some opcodes that simplify
|
||||
parsing and semantic interpretation.
|
||||
"""
|
||||
|
||||
cmp_op = ('<', '<=', '==', '!=', '>', '>=', 'in', 'not in', 'is',
|
||||
'is not', 'exception match', 'BAD')
|
||||
from copy import deepcopy
|
||||
|
||||
hasconst = []
|
||||
hasname = []
|
||||
hasjrel = []
|
||||
hasjabs = []
|
||||
haslocal = []
|
||||
hascompare = []
|
||||
hasfree = []
|
||||
hasnargs = []
|
||||
import uncompyle6.opcodes.opcode_3x as opcode_3x
|
||||
from uncompyle6.opcodes.opcode_3x import fields2copy, hasfree, rm_op
|
||||
|
||||
# FIXME: can we DRY this even more?
|
||||
|
||||
opmap = {}
|
||||
opname = [''] * 256
|
||||
for op in range(256): opname[op] = '<%r>' % (op,)
|
||||
del op
|
||||
hasconst = []
|
||||
hasjrel = []
|
||||
hasjabs = []
|
||||
|
||||
def def_op(name, op):
|
||||
opname[op] = name
|
||||
opmap[name] = op
|
||||
|
||||
def name_op(name, op):
|
||||
def_op(name, op)
|
||||
hasname.append(op)
|
||||
for object in fields2copy:
|
||||
globals()[object] = deepcopy(getattr(opcode_3x, object))
|
||||
|
||||
def jrel_op(name, op):
|
||||
def_op(name, op)
|
||||
hasjrel.append(op)
|
||||
# Below are opcodes changes since Python 3.2
|
||||
|
||||
def jabs_op(name, op):
|
||||
def_op(name, op)
|
||||
hasjabs.append(op)
|
||||
rm_op(opname, opmap, 'STOP_CODE', 0)
|
||||
rm_op(opname, opmap, 'STORE_LOCALS', 69)
|
||||
|
||||
# These are new since Python 3.3
|
||||
def_op('YIELD_FROM', 72)
|
||||
def_op('LOAD_CLASSDEREF', 148)
|
||||
hasfree.append(148)
|
||||
|
||||
def updateGlobal():
|
||||
# JUMP_OPs are used in verification are set in the scanner
|
||||
@@ -50,171 +47,15 @@ def updateGlobal():
|
||||
globals().update(dict([(k.replace('+', '_'), v) for (k, v) in opmap.items()]))
|
||||
globals().update({'JUMP_OPs': map(lambda op: opname[op], hasjrel + hasjabs)})
|
||||
|
||||
# Instruction opcodes for compiled code
|
||||
# Blank lines correspond to available opcodes
|
||||
|
||||
def_op('STOP_CODE', 0)
|
||||
def_op('POP_TOP', 1)
|
||||
def_op('ROT_TWO', 2)
|
||||
def_op('ROT_THREE', 3)
|
||||
def_op('DUP_TOP', 4)
|
||||
def_op('DUP_TOP_TWO', 5)
|
||||
|
||||
def_op('NOP', 9)
|
||||
def_op('UNARY_POSITIVE', 10)
|
||||
def_op('UNARY_NEGATIVE', 11)
|
||||
def_op('UNARY_NOT', 12)
|
||||
|
||||
def_op('UNARY_INVERT', 15)
|
||||
|
||||
def_op('BINARY_POWER', 19)
|
||||
def_op('BINARY_MULTIPLY', 20)
|
||||
|
||||
def_op('BINARY_MODULO', 22)
|
||||
def_op('BINARY_ADD', 23)
|
||||
def_op('BINARY_SUBTRACT', 24)
|
||||
def_op('BINARY_SUBSCR', 25)
|
||||
def_op('BINARY_FLOOR_DIVIDE', 26)
|
||||
def_op('BINARY_TRUE_DIVIDE', 27)
|
||||
def_op('INPLACE_FLOOR_DIVIDE', 28)
|
||||
def_op('INPLACE_TRUE_DIVIDE', 29)
|
||||
|
||||
# Gone from Python 3 are Python2's
|
||||
# SLICE+0 .. SLICE+3
|
||||
# STORE_SLICE+0 .. STORE_SLICE+3
|
||||
# DELETE_SLICE+0 .. DELETE_SLICE+3
|
||||
|
||||
def_op('STORE_MAP', 54)
|
||||
def_op('INPLACE_ADD', 55)
|
||||
def_op('INPLACE_SUBTRACT', 56)
|
||||
def_op('INPLACE_MULTIPLY', 57)
|
||||
|
||||
def_op('INPLACE_MODULO', 59)
|
||||
def_op('STORE_SUBSCR', 60)
|
||||
def_op('DELETE_SUBSCR', 61)
|
||||
def_op('BINARY_LSHIFT', 62)
|
||||
def_op('BINARY_RSHIFT', 63)
|
||||
def_op('BINARY_AND', 64)
|
||||
def_op('BINARY_XOR', 65)
|
||||
def_op('BINARY_OR', 66)
|
||||
def_op('INPLACE_POWER', 67)
|
||||
def_op('GET_ITER', 68)
|
||||
|
||||
# FIXME: no code generates this
|
||||
def_op('STORE_LOCALS', 69)
|
||||
|
||||
def_op('PRINT_EXPR', 70)
|
||||
def_op('LOAD_BUILD_CLASS', 71)
|
||||
def_op('YIELD_FROM', 72)
|
||||
|
||||
# Python3 drops/changes:
|
||||
# def_op('PRINT_ITEM', 71)
|
||||
# def_op('PRINT_NEWLINE', 72)
|
||||
# def_op('PRINT_ITEM_TO', 73)
|
||||
# def_op('PRINT_NEWLINE_TO', 74)
|
||||
|
||||
def_op('INPLACE_LSHIFT', 75)
|
||||
def_op('INPLACE_RSHIFT', 76)
|
||||
def_op('INPLACE_AND', 77)
|
||||
def_op('INPLACE_XOR', 78)
|
||||
def_op('INPLACE_OR', 79)
|
||||
def_op('BREAK_LOOP', 80)
|
||||
def_op('WITH_CLEANUP', 81)
|
||||
|
||||
def_op('RETURN_VALUE', 83)
|
||||
def_op('IMPORT_STAR', 84)
|
||||
|
||||
def_op('YIELD_VALUE', 86)
|
||||
def_op('POP_BLOCK', 87)
|
||||
def_op('END_FINALLY', 88)
|
||||
def_op('POP_EXCEPT', 89)
|
||||
|
||||
HAVE_ARGUMENT = 90 # Opcodes from here have an argument:
|
||||
|
||||
name_op('STORE_NAME', 90) # Index in name list
|
||||
name_op('DELETE_NAME', 91) # ""
|
||||
def_op('UNPACK_SEQUENCE', 92) # Number of tuple items
|
||||
jrel_op('FOR_ITER', 93)
|
||||
def_op('UNPACK_EX', 94)
|
||||
name_op('STORE_ATTR', 95) # Index in name list
|
||||
name_op('DELETE_ATTR', 96) # ""
|
||||
name_op('STORE_GLOBAL', 97) # ""
|
||||
name_op('DELETE_GLOBAL', 98) # ""
|
||||
|
||||
# Python 2's DUP_TOPX is gone
|
||||
|
||||
def_op('LOAD_CONST', 100) # Index in const list
|
||||
hasconst.append(100)
|
||||
name_op('LOAD_NAME', 101) # Index in name list
|
||||
def_op('BUILD_TUPLE', 102) # Number of tuple items
|
||||
def_op('BUILD_LIST', 103) # Number of list items
|
||||
def_op('BUILD_SET', 104) # Number of set items
|
||||
def_op('BUILD_MAP', 105) # Number of dict entries (upto 255)
|
||||
name_op('LOAD_ATTR', 106) # Index in name list
|
||||
def_op('COMPARE_OP', 107) # Comparison operator
|
||||
hascompare.append(107)
|
||||
name_op('IMPORT_NAME', 108) # Index in name list
|
||||
name_op('IMPORT_FROM', 109) # Index in name list
|
||||
|
||||
jrel_op('JUMP_FORWARD', 110) # Number of bytes to skip
|
||||
jabs_op('JUMP_IF_FALSE_OR_POP', 111) # Target byte offset from beginning of code
|
||||
jabs_op('JUMP_IF_TRUE_OR_POP', 112) # ""
|
||||
jabs_op('JUMP_ABSOLUTE', 113) # ""
|
||||
jabs_op('POP_JUMP_IF_FALSE', 114) # ""
|
||||
jabs_op('POP_JUMP_IF_TRUE', 115) # ""
|
||||
|
||||
name_op('LOAD_GLOBAL', 116) # Index in name list
|
||||
|
||||
jabs_op('CONTINUE_LOOP', 119) # Target address
|
||||
jrel_op('SETUP_LOOP', 120) # Distance to target address
|
||||
jrel_op('SETUP_EXCEPT', 121) # ""
|
||||
jrel_op('SETUP_FINALLY', 122) # ""
|
||||
|
||||
def_op('LOAD_FAST', 124) # Local variable number
|
||||
haslocal.append(124)
|
||||
def_op('STORE_FAST', 125) # Local variable number
|
||||
haslocal.append(125)
|
||||
def_op('DELETE_FAST', 126) # Local variable number
|
||||
haslocal.append(126)
|
||||
|
||||
def_op('RAISE_VARARGS', 130) # Number of raise arguments (1, 2, or 3)
|
||||
def_op('CALL_FUNCTION', 131) # #args + (#kwargs << 8)
|
||||
hasnargs.append(131)
|
||||
def_op('MAKE_FUNCTION', 132) # Number of args with default values
|
||||
def_op('BUILD_SLICE', 133) # Number of items
|
||||
def_op('MAKE_CLOSURE', 134)
|
||||
def_op('LOAD_CLOSURE', 135)
|
||||
hasfree.append(135)
|
||||
def_op('LOAD_DEREF', 136)
|
||||
hasfree.append(136)
|
||||
def_op('STORE_DEREF', 137)
|
||||
hasfree.append(137)
|
||||
def_op('DELETE_DEREF', 138)
|
||||
hasfree.append(138)
|
||||
|
||||
def_op('CALL_FUNCTION_VAR', 140) # #args + (#kwargs << 8)
|
||||
hasnargs.append(140)
|
||||
def_op('CALL_FUNCTION_KW', 141) # #args + (#kwargs << 8)
|
||||
hasnargs.append(141)
|
||||
def_op('CALL_FUNCTION_VAR_KW', 142) # #args + (#kwargs << 8)
|
||||
hasnargs.append(142)
|
||||
|
||||
jrel_op('SETUP_WITH', 143)
|
||||
|
||||
def_op('LIST_APPEND', 145)
|
||||
def_op('SET_ADD', 146)
|
||||
def_op('MAP_ADD', 147)
|
||||
|
||||
def_op('LOAD_CLASSDEREF', 148)
|
||||
hasfree.append(148)
|
||||
|
||||
def_op('EXTENDED_ARG', 144)
|
||||
EXTENDED_ARG = 144
|
||||
|
||||
updateGlobal()
|
||||
del def_op, name_op, jrel_op, jabs_op
|
||||
|
||||
# FIXME: turn into pytest test
|
||||
from uncompyle6 import PYTHON_VERSION
|
||||
if PYTHON_VERSION == 3.4:
|
||||
import dis
|
||||
# for item in dis.opmap.items():
|
||||
# if item not in opmap.items():
|
||||
# print(item)
|
||||
assert all(item in opmap.items() for item in dis.opmap.items())
|
||||
|
||||
# opcode_3x.dump_opcodes(opmap)
|
||||
|
84
uncompyle6/opcodes/opcode_35.py
Normal file
84
uncompyle6/opcodes/opcode_35.py
Normal file
@@ -0,0 +1,84 @@
|
||||
# (C) Copyright 2016 by Rocky Bernstein
|
||||
"""
|
||||
CPython 3.5 bytecode opcodes
|
||||
|
||||
used in scanner (bytecode disassembly) and parser (Python grammar)
|
||||
|
||||
This is a superset of Python 3.5's opcode.py with some opcodes that simplify
|
||||
parsing and semantic interpretation.
|
||||
"""
|
||||
|
||||
from copy import deepcopy
|
||||
|
||||
import uncompyle6.opcodes.opcode_3x as opcode_3x
|
||||
from uncompyle6.opcodes.opcode_3x import fields2copy, hasfree, rm_op
|
||||
|
||||
# FIXME: can we DRY this even more?
|
||||
|
||||
opmap = {}
|
||||
opname = [''] * 256
|
||||
hasconst = []
|
||||
hasjrel = []
|
||||
hasjabs = []
|
||||
|
||||
def def_op(name, op):
|
||||
opname[op] = name
|
||||
opmap[name] = op
|
||||
|
||||
for object in fields2copy:
|
||||
globals()[object] = deepcopy(getattr(opcode_3x, object))
|
||||
|
||||
# Below are opcodes changes since Python 3.2
|
||||
|
||||
rm_op(opname, opmap, 'STOP_CODE', 0)
|
||||
rm_op(opname, opmap, 'STORE_LOCALS', 69)
|
||||
|
||||
# These are new since Python 3.3
|
||||
def_op('YIELD_FROM', 72)
|
||||
def_op('LOAD_CLASSDEREF', 148)
|
||||
|
||||
# These are removed since Python 3.4
|
||||
rm_op(opname, opmap, 'WITH_CLEANUP', 81)
|
||||
|
||||
# These are new since Python 3.4
|
||||
def_op('BINARY_MATRIX_MULTIPLY', 16)
|
||||
def_op('INPLACE_MATRIX_MULTIPLY', 17)
|
||||
def_op('GET_AITER', 50)
|
||||
def_op('GET_ANEXT', 51)
|
||||
def_op('BEFORE_ASYNC_WITH', 52)
|
||||
def_op('GET_YIELD_FROM_ITER', 69)
|
||||
def_op('GET_AWAITABLE', 73)
|
||||
def_op('WITH_CLEANUP_START', 81)
|
||||
def_op('WITH_CLEANUP_FINISH', 82)
|
||||
def_op('BUILD_LIST_UNPACK', 149)
|
||||
def_op('BUILD_MAP_UNPACK', 150)
|
||||
def_op('BUILD_MAP_UNPACK_WITH_CALL', 151)
|
||||
def_op('BUILD_TUPLE_UNPACK', 152)
|
||||
def_op('BUILD_SET_UNPACK', 153)
|
||||
def_op('SETUP_ASYNC_WITH', 154)
|
||||
|
||||
|
||||
hasfree.append(148)
|
||||
|
||||
def updateGlobal():
|
||||
# JUMP_OPs are used in verification are set in the scanner
|
||||
# and used in the parser grammar
|
||||
globals().update({'PJIF': opmap['POP_JUMP_IF_FALSE']})
|
||||
globals().update({'PJIT': opmap['POP_JUMP_IF_TRUE']})
|
||||
globals().update({'JA': opmap['JUMP_ABSOLUTE']})
|
||||
globals().update({'JF': opmap['JUMP_FORWARD']})
|
||||
globals().update(dict([(k.replace('+', '_'), v) for (k, v) in opmap.items()]))
|
||||
globals().update({'JUMP_OPs': map(lambda op: opname[op], hasjrel + hasjabs)})
|
||||
|
||||
updateGlobal()
|
||||
|
||||
# FIXME: turn into pytest test
|
||||
from uncompyle6 import PYTHON_VERSION
|
||||
if PYTHON_VERSION == 3.5:
|
||||
import dis
|
||||
for item in dis.opmap.items():
|
||||
if item not in opmap.items():
|
||||
print(item)
|
||||
assert all(item in opmap.items() for item in dis.opmap.items())
|
||||
|
||||
# opcode_3x.dump_opcodes(opmap)
|
210
uncompyle6/opcodes/opcode_3x.py
Normal file
210
uncompyle6/opcodes/opcode_3x.py
Normal file
@@ -0,0 +1,210 @@
|
||||
"""
|
||||
CPython 3.2 bytecode opcodes to be used as a base for other opcodes including 3.2.
|
||||
If this file changes the other opcode files may have to a adjusted accordingly.
|
||||
"""
|
||||
|
||||
cmp_op = ('<', '<=', '==', '!=', '>', '>=', 'in', 'not in', 'is',
|
||||
'is not', 'exception match', 'BAD')
|
||||
|
||||
hasconst = []
|
||||
hasname = []
|
||||
hasjrel = []
|
||||
hasjabs = []
|
||||
haslocal = []
|
||||
hascompare = []
|
||||
hasfree = []
|
||||
hasnargs = []
|
||||
|
||||
opmap = {}
|
||||
opname = [''] * 256
|
||||
for op in range(256): opname[op] = '<%r>' % (op,)
|
||||
del op
|
||||
|
||||
def def_op(name, op):
|
||||
opname[op] = name
|
||||
opmap[name] = op
|
||||
|
||||
def name_op(name, op):
|
||||
def_op(name, op)
|
||||
hasname.append(op)
|
||||
|
||||
def jrel_op(name, op):
|
||||
def_op(name, op)
|
||||
hasjrel.append(op)
|
||||
|
||||
def jabs_op(name, op):
|
||||
def_op(name, op)
|
||||
hasjabs.append(op)
|
||||
|
||||
# Instruction opcodes for compiled code
|
||||
# Blank lines correspond to available opcodes
|
||||
|
||||
def_op('STOP_CODE', 0)
|
||||
def_op('POP_TOP', 1)
|
||||
def_op('ROT_TWO', 2)
|
||||
def_op('ROT_THREE', 3)
|
||||
def_op('DUP_TOP', 4)
|
||||
def_op('DUP_TOP_TWO', 5)
|
||||
|
||||
def_op('NOP', 9)
|
||||
def_op('UNARY_POSITIVE', 10)
|
||||
def_op('UNARY_NEGATIVE', 11)
|
||||
def_op('UNARY_NOT', 12)
|
||||
|
||||
def_op('UNARY_INVERT', 15)
|
||||
|
||||
def_op('BINARY_POWER', 19)
|
||||
def_op('BINARY_MULTIPLY', 20)
|
||||
|
||||
def_op('BINARY_MODULO', 22)
|
||||
def_op('BINARY_ADD', 23)
|
||||
def_op('BINARY_SUBTRACT', 24)
|
||||
def_op('BINARY_SUBSCR', 25)
|
||||
def_op('BINARY_FLOOR_DIVIDE', 26)
|
||||
def_op('BINARY_TRUE_DIVIDE', 27)
|
||||
def_op('INPLACE_FLOOR_DIVIDE', 28)
|
||||
def_op('INPLACE_TRUE_DIVIDE', 29)
|
||||
|
||||
# Gone from Python 3 are Python2's
|
||||
# SLICE+0 .. SLICE+3
|
||||
# STORE_SLICE+0 .. STORE_SLICE+3
|
||||
# DELETE_SLICE+0 .. DELETE_SLICE+3
|
||||
|
||||
def_op('STORE_MAP', 54)
|
||||
def_op('INPLACE_ADD', 55)
|
||||
def_op('INPLACE_SUBTRACT', 56)
|
||||
def_op('INPLACE_MULTIPLY', 57)
|
||||
|
||||
def_op('INPLACE_MODULO', 59)
|
||||
def_op('STORE_SUBSCR', 60)
|
||||
def_op('DELETE_SUBSCR', 61)
|
||||
def_op('BINARY_LSHIFT', 62)
|
||||
def_op('BINARY_RSHIFT', 63)
|
||||
def_op('BINARY_AND', 64)
|
||||
def_op('BINARY_XOR', 65)
|
||||
def_op('BINARY_OR', 66)
|
||||
def_op('INPLACE_POWER', 67)
|
||||
def_op('GET_ITER', 68)
|
||||
def_op('STORE_LOCALS', 69)
|
||||
|
||||
def_op('PRINT_EXPR', 70)
|
||||
def_op('LOAD_BUILD_CLASS', 71)
|
||||
|
||||
# Python3 drops/changes:
|
||||
# def_op('PRINT_ITEM', 71)
|
||||
# def_op('PRINT_NEWLINE', 72)
|
||||
# def_op('PRINT_ITEM_TO', 73)
|
||||
# def_op('PRINT_NEWLINE_TO', 74)
|
||||
|
||||
def_op('INPLACE_LSHIFT', 75)
|
||||
def_op('INPLACE_RSHIFT', 76)
|
||||
def_op('INPLACE_AND', 77)
|
||||
def_op('INPLACE_XOR', 78)
|
||||
def_op('INPLACE_OR', 79)
|
||||
def_op('BREAK_LOOP', 80)
|
||||
def_op('WITH_CLEANUP', 81)
|
||||
|
||||
def_op('RETURN_VALUE', 83)
|
||||
def_op('IMPORT_STAR', 84)
|
||||
|
||||
def_op('YIELD_VALUE', 86)
|
||||
def_op('POP_BLOCK', 87)
|
||||
def_op('END_FINALLY', 88)
|
||||
def_op('POP_EXCEPT', 89)
|
||||
|
||||
HAVE_ARGUMENT = 90 # Opcodes from here have an argument:
|
||||
|
||||
name_op('STORE_NAME', 90) # Index in name list
|
||||
name_op('DELETE_NAME', 91) # ""
|
||||
def_op('UNPACK_SEQUENCE', 92) # Number of tuple items
|
||||
jrel_op('FOR_ITER', 93)
|
||||
def_op('UNPACK_EX', 94)
|
||||
name_op('STORE_ATTR', 95) # Index in name list
|
||||
name_op('DELETE_ATTR', 96) # ""
|
||||
name_op('STORE_GLOBAL', 97) # ""
|
||||
name_op('DELETE_GLOBAL', 98) # ""
|
||||
|
||||
# Python 2's DUP_TOPX is gone
|
||||
|
||||
def_op('LOAD_CONST', 100) # Index in const list
|
||||
hasconst.append(100)
|
||||
name_op('LOAD_NAME', 101) # Index in name list
|
||||
def_op('BUILD_TUPLE', 102) # Number of tuple items
|
||||
def_op('BUILD_LIST', 103) # Number of list items
|
||||
def_op('BUILD_SET', 104) # Number of set items
|
||||
def_op('BUILD_MAP', 105) # Number of dict entries (upto 255)
|
||||
name_op('LOAD_ATTR', 106) # Index in name list
|
||||
def_op('COMPARE_OP', 107) # Comparison operator
|
||||
hascompare.append(107)
|
||||
name_op('IMPORT_NAME', 108) # Index in name list
|
||||
name_op('IMPORT_FROM', 109) # Index in name list
|
||||
|
||||
jrel_op('JUMP_FORWARD', 110) # Number of bytes to skip
|
||||
jabs_op('JUMP_IF_FALSE_OR_POP', 111) # Target byte offset from beginning of code
|
||||
jabs_op('JUMP_IF_TRUE_OR_POP', 112) # ""
|
||||
jabs_op('JUMP_ABSOLUTE', 113) # ""
|
||||
jabs_op('POP_JUMP_IF_FALSE', 114) # ""
|
||||
jabs_op('POP_JUMP_IF_TRUE', 115) # ""
|
||||
|
||||
name_op('LOAD_GLOBAL', 116) # Index in name list
|
||||
|
||||
jabs_op('CONTINUE_LOOP', 119) # Target address
|
||||
jrel_op('SETUP_LOOP', 120) # Distance to target address
|
||||
jrel_op('SETUP_EXCEPT', 121) # ""
|
||||
jrel_op('SETUP_FINALLY', 122) # ""
|
||||
|
||||
def_op('LOAD_FAST', 124) # Local variable number
|
||||
haslocal.append(124)
|
||||
def_op('STORE_FAST', 125) # Local variable number
|
||||
haslocal.append(125)
|
||||
def_op('DELETE_FAST', 126) # Local variable number
|
||||
haslocal.append(126)
|
||||
|
||||
def_op('RAISE_VARARGS', 130) # Number of raise arguments (1, 2, or 3)
|
||||
def_op('CALL_FUNCTION', 131) # #args + (#kwargs << 8)
|
||||
hasnargs.append(131)
|
||||
def_op('MAKE_FUNCTION', 132) # Number of args with default values
|
||||
def_op('BUILD_SLICE', 133) # Number of items
|
||||
def_op('MAKE_CLOSURE', 134)
|
||||
def_op('LOAD_CLOSURE', 135)
|
||||
hasfree.append(135)
|
||||
def_op('LOAD_DEREF', 136)
|
||||
hasfree.append(136)
|
||||
def_op('STORE_DEREF', 137)
|
||||
hasfree.append(137)
|
||||
def_op('DELETE_DEREF', 138)
|
||||
hasfree.append(138)
|
||||
|
||||
def_op('CALL_FUNCTION_VAR', 140) # #args + (#kwargs << 8)
|
||||
hasnargs.append(140)
|
||||
def_op('CALL_FUNCTION_KW', 141) # #args + (#kwargs << 8)
|
||||
hasnargs.append(141)
|
||||
def_op('CALL_FUNCTION_VAR_KW', 142) # #args + (#kwargs << 8)
|
||||
hasnargs.append(142)
|
||||
|
||||
jrel_op('SETUP_WITH', 143)
|
||||
|
||||
def_op('LIST_APPEND', 145)
|
||||
def_op('SET_ADD', 146)
|
||||
def_op('MAP_ADD', 147)
|
||||
|
||||
def_op('EXTENDED_ARG', 144)
|
||||
EXTENDED_ARG = 144
|
||||
|
||||
fields2copy = """cmp_op hasconst hasname hasjrel hasjabs haslocal hascompare hasfree hasnargs
|
||||
opmap opname HAVE_ARGUMENT EXTENDED_ARG""".split()
|
||||
|
||||
def rm_op(opname, opmap, name, op):
|
||||
# opname is an array, so we need to keep the position in there.
|
||||
opname[op] = ''
|
||||
|
||||
assert opmap[name] == op
|
||||
del opmap[name]
|
||||
|
||||
def dump_opcodes(opmap):
|
||||
"""Utility for dumping opcodes"""
|
||||
op2name = {}
|
||||
for k in opmap.keys():
|
||||
op2name[opmap[k]] = k
|
||||
for i in sorted(op2name.keys()):
|
||||
print("%-3s %s" % (str(i), op2name[i]))
|
@@ -1,9 +1,9 @@
|
||||
# Copyright (c) 1999 John Aycock
|
||||
# Copyright (c) 2000-2002 by hartmut Goebel <h.goebel@crazy-compilers.com>
|
||||
# Copyright (c) 2015-2016 Rocky Bernstein
|
||||
# Copyright (c) 2005 by Dan Pascu <dan@windowmaker.org>
|
||||
# Copyright (c) 2015 Rocky Bernstein
|
||||
# Copyright (c) 2000-2002 by hartmut Goebel <h.goebel@crazy-compilers.com>
|
||||
# Copyright (c) 1999 John Aycock
|
||||
"""
|
||||
Common spark parser routines Python.
|
||||
Common uncompyle parser routines.
|
||||
"""
|
||||
|
||||
from __future__ import print_function
|
||||
@@ -11,7 +11,7 @@ from __future__ import print_function
|
||||
import sys
|
||||
|
||||
from uncompyle6.code import iscode
|
||||
from uncompyle6.parsers.spark import GenericASTBuilder, DEFAULT_DEBUG as PARSER_DEFAULT_DEBUG
|
||||
from spark_parser import GenericASTBuilder, DEFAULT_DEBUG as PARSER_DEFAULT_DEBUG
|
||||
|
||||
class ParserError(Exception):
|
||||
def __init__(self, token, offset):
|
||||
@@ -69,6 +69,323 @@ class PythonParser(GenericASTBuilder):
|
||||
# print >> sys.stderr, 'resolve', str(list)
|
||||
return GenericASTBuilder.resolve(self, list)
|
||||
|
||||
##############################################
|
||||
## Common Python 2 and Python 3 grammar rules
|
||||
##############################################
|
||||
def p_start(self, args):
|
||||
'''
|
||||
# The start or goal symbol
|
||||
stmts ::= stmts sstmt
|
||||
stmts ::= sstmt
|
||||
'''
|
||||
|
||||
def p_call_stmt(self, args):
|
||||
'''
|
||||
# eval-mode compilation. Single-mode interactive compilation
|
||||
# adds another rule.
|
||||
call_stmt ::= expr POP_TOP
|
||||
'''
|
||||
|
||||
def p_funcdef(self, args):
|
||||
'''
|
||||
stmt ::= funcdef
|
||||
funcdef ::= mkfunc designator
|
||||
stmt ::= funcdefdeco
|
||||
funcdefdeco ::= mkfuncdeco designator
|
||||
mkfuncdeco ::= expr mkfuncdeco CALL_FUNCTION_1
|
||||
mkfuncdeco ::= expr mkfuncdeco0 CALL_FUNCTION_1
|
||||
mkfuncdeco0 ::= mkfunc
|
||||
load_closure ::= load_closure LOAD_CLOSURE
|
||||
load_closure ::= LOAD_CLOSURE
|
||||
'''
|
||||
|
||||
def p_genexpr(self, args):
|
||||
'''
|
||||
expr ::= genexpr
|
||||
|
||||
genexpr ::= LOAD_GENEXPR MAKE_FUNCTION_0 expr GET_ITER CALL_FUNCTION_1
|
||||
|
||||
stmt ::= genexpr_func
|
||||
|
||||
genexpr_func ::= LOAD_FAST FOR_ITER designator comp_iter JUMP_BACK
|
||||
'''
|
||||
|
||||
def p_dictcomp(self, args):
|
||||
'''
|
||||
expr ::= dictcomp
|
||||
dictcomp ::= LOAD_DICTCOMP MAKE_FUNCTION_0 expr GET_ITER CALL_FUNCTION_1
|
||||
stmt ::= dictcomp_func
|
||||
|
||||
dictcomp_func ::= BUILD_MAP LOAD_FAST FOR_ITER designator
|
||||
comp_iter JUMP_BACK RETURN_VALUE RETURN_LAST
|
||||
|
||||
'''
|
||||
|
||||
def p_augmented_assign(self, args):
|
||||
'''
|
||||
stmt ::= augassign1
|
||||
stmt ::= augassign2
|
||||
augassign1 ::= expr expr inplace_op designator
|
||||
augassign1 ::= expr expr inplace_op ROT_THREE STORE_SUBSCR
|
||||
augassign1 ::= expr expr inplace_op ROT_TWO STORE_SLICE+0
|
||||
augassign1 ::= expr expr inplace_op ROT_THREE STORE_SLICE+1
|
||||
augassign1 ::= expr expr inplace_op ROT_THREE STORE_SLICE+2
|
||||
augassign1 ::= expr expr inplace_op ROT_FOUR STORE_SLICE+3
|
||||
augassign2 ::= expr DUP_TOP LOAD_ATTR expr
|
||||
inplace_op ROT_TWO STORE_ATTR
|
||||
|
||||
inplace_op ::= INPLACE_ADD
|
||||
inplace_op ::= INPLACE_SUBTRACT
|
||||
inplace_op ::= INPLACE_MULTIPLY
|
||||
inplace_op ::= INPLACE_DIVIDE
|
||||
inplace_op ::= INPLACE_TRUE_DIVIDE
|
||||
inplace_op ::= INPLACE_FLOOR_DIVIDE
|
||||
inplace_op ::= INPLACE_MODULO
|
||||
inplace_op ::= INPLACE_POWER
|
||||
inplace_op ::= INPLACE_LSHIFT
|
||||
inplace_op ::= INPLACE_RSHIFT
|
||||
inplace_op ::= INPLACE_AND
|
||||
inplace_op ::= INPLACE_XOR
|
||||
inplace_op ::= INPLACE_OR
|
||||
'''
|
||||
|
||||
def p_assign(self, args):
|
||||
'''
|
||||
stmt ::= assign
|
||||
assign ::= expr DUP_TOP designList
|
||||
assign ::= expr designator
|
||||
|
||||
stmt ::= assign2
|
||||
stmt ::= assign3
|
||||
assign2 ::= expr expr ROT_TWO designator designator
|
||||
assign3 ::= expr expr expr ROT_THREE ROT_TWO designator designator designator
|
||||
'''
|
||||
|
||||
def p_import20(self, args):
|
||||
'''
|
||||
stmt ::= importstmt
|
||||
stmt ::= importfrom
|
||||
stmt ::= importstar
|
||||
stmt ::= importmultiple
|
||||
|
||||
importlist2 ::= importlist2 import_as
|
||||
importlist2 ::= import_as
|
||||
import_as ::= IMPORT_NAME designator
|
||||
import_as ::= IMPORT_NAME load_attrs designator
|
||||
import_as ::= IMPORT_FROM designator
|
||||
|
||||
importstmt ::= LOAD_CONST LOAD_CONST import_as
|
||||
importstar ::= LOAD_CONST LOAD_CONST IMPORT_NAME IMPORT_STAR
|
||||
importfrom ::= LOAD_CONST LOAD_CONST IMPORT_NAME importlist2 POP_TOP
|
||||
importstar ::= LOAD_CONST LOAD_CONST IMPORT_NAME_CONT IMPORT_STAR
|
||||
importfrom ::= LOAD_CONST LOAD_CONST IMPORT_NAME_CONT importlist2 POP_TOP
|
||||
importmultiple ::= LOAD_CONST LOAD_CONST import_as imports_cont
|
||||
|
||||
imports_cont ::= imports_cont import_cont
|
||||
imports_cont ::= import_cont
|
||||
import_cont ::= LOAD_CONST LOAD_CONST import_as_cont
|
||||
import_as_cont ::= IMPORT_NAME_CONT designator
|
||||
import_as_cont ::= IMPORT_NAME_CONT load_attrs designator
|
||||
import_as_cont ::= IMPORT_FROM designator
|
||||
|
||||
load_attrs ::= LOAD_ATTR
|
||||
load_attrs ::= load_attrs LOAD_ATTR
|
||||
'''
|
||||
|
||||
def p_list_comprehension(self, args):
|
||||
"""
|
||||
expr ::= list_compr
|
||||
list_compr ::= BUILD_LIST_0 list_iter
|
||||
|
||||
list_iter ::= list_for
|
||||
list_iter ::= list_if
|
||||
list_iter ::= list_if_not
|
||||
list_iter ::= lc_body
|
||||
|
||||
_come_from ::= COME_FROM
|
||||
_come_from ::=
|
||||
|
||||
list_if ::= expr jmp_false list_iter
|
||||
list_if_not ::= expr jmp_true list_iter
|
||||
|
||||
lc_body ::= expr LIST_APPEND
|
||||
"""
|
||||
|
||||
def p_setcomp(self, args):
|
||||
"""
|
||||
expr ::= setcomp
|
||||
|
||||
setcomp ::= LOAD_SETCOMP MAKE_FUNCTION_0 expr GET_ITER CALL_FUNCTION_1
|
||||
|
||||
stmt ::= setcomp_func
|
||||
|
||||
setcomp_func ::= BUILD_SET_0 LOAD_FAST FOR_ITER designator comp_iter
|
||||
JUMP_BACK RETURN_VALUE RETURN_LAST
|
||||
|
||||
comp_iter ::= comp_if
|
||||
comp_iter ::= comp_ifnot
|
||||
comp_iter ::= comp_for
|
||||
comp_iter ::= comp_body
|
||||
comp_body ::= set_comp_body
|
||||
comp_body ::= gen_comp_body
|
||||
comp_body ::= dict_comp_body
|
||||
set_comp_body ::= expr SET_ADD
|
||||
gen_comp_body ::= expr YIELD_VALUE POP_TOP
|
||||
dict_comp_body ::= expr expr MAP_ADD
|
||||
|
||||
comp_if ::= expr jmp_false comp_iter
|
||||
comp_ifnot ::= expr jmp_true comp_iter
|
||||
"""
|
||||
|
||||
def p_expr(self, args):
|
||||
'''
|
||||
expr ::= _mklambda
|
||||
expr ::= SET_LINENO
|
||||
expr ::= LOAD_FAST
|
||||
expr ::= LOAD_NAME
|
||||
expr ::= LOAD_CONST
|
||||
expr ::= LOAD_GLOBAL
|
||||
expr ::= LOAD_DEREF
|
||||
expr ::= load_attr
|
||||
expr ::= binary_expr
|
||||
expr ::= binary_expr_na
|
||||
expr ::= build_list
|
||||
expr ::= cmp
|
||||
expr ::= mapexpr
|
||||
expr ::= and
|
||||
expr ::= and2
|
||||
expr ::= or
|
||||
expr ::= unary_expr
|
||||
expr ::= call_function
|
||||
expr ::= unary_not
|
||||
expr ::= unary_convert
|
||||
expr ::= binary_subscr
|
||||
expr ::= binary_subscr2
|
||||
expr ::= load_attr
|
||||
expr ::= get_iter
|
||||
expr ::= slice0
|
||||
expr ::= slice1
|
||||
expr ::= slice2
|
||||
expr ::= slice3
|
||||
expr ::= buildslice2
|
||||
expr ::= buildslice3
|
||||
expr ::= yield
|
||||
|
||||
binary_expr ::= expr expr binary_op
|
||||
binary_op ::= BINARY_ADD
|
||||
binary_op ::= BINARY_MULTIPLY
|
||||
binary_op ::= BINARY_AND
|
||||
binary_op ::= BINARY_OR
|
||||
binary_op ::= BINARY_XOR
|
||||
binary_op ::= BINARY_SUBTRACT
|
||||
binary_op ::= BINARY_DIVIDE
|
||||
binary_op ::= BINARY_TRUE_DIVIDE
|
||||
binary_op ::= BINARY_FLOOR_DIVIDE
|
||||
binary_op ::= BINARY_MODULO
|
||||
binary_op ::= BINARY_LSHIFT
|
||||
binary_op ::= BINARY_RSHIFT
|
||||
binary_op ::= BINARY_POWER
|
||||
|
||||
unary_expr ::= expr unary_op
|
||||
unary_op ::= UNARY_POSITIVE
|
||||
unary_op ::= UNARY_NEGATIVE
|
||||
unary_op ::= UNARY_INVERT
|
||||
|
||||
unary_not ::= expr UNARY_NOT
|
||||
unary_convert ::= expr UNARY_CONVERT
|
||||
|
||||
binary_subscr ::= expr expr BINARY_SUBSCR
|
||||
binary_subscr2 ::= expr expr DUP_TOPX_2 BINARY_SUBSCR
|
||||
|
||||
load_attr ::= expr LOAD_ATTR
|
||||
get_iter ::= expr GET_ITER
|
||||
slice0 ::= expr SLICE+0
|
||||
slice0 ::= expr DUP_TOP SLICE+0
|
||||
slice1 ::= expr expr SLICE+1
|
||||
slice1 ::= expr expr DUP_TOPX_2 SLICE+1
|
||||
slice2 ::= expr expr SLICE+2
|
||||
slice2 ::= expr expr DUP_TOPX_2 SLICE+2
|
||||
slice3 ::= expr expr expr SLICE+3
|
||||
slice3 ::= expr expr expr DUP_TOPX_3 SLICE+3
|
||||
buildslice3 ::= expr expr expr BUILD_SLICE_3
|
||||
buildslice2 ::= expr expr BUILD_SLICE_2
|
||||
|
||||
yield ::= expr YIELD_VALUE
|
||||
|
||||
_mklambda ::= load_closure mklambda
|
||||
_mklambda ::= mklambda
|
||||
|
||||
or ::= expr JUMP_IF_TRUE_OR_POP expr COME_FROM
|
||||
or ::= expr jmp_true expr _come_from
|
||||
and ::= expr jmp_false expr _come_from
|
||||
and ::= expr JUMP_IF_FALSE_OR_POP expr COME_FROM
|
||||
and2 ::= _jump jmp_false COME_FROM expr COME_FROM
|
||||
|
||||
expr ::= conditional
|
||||
conditional ::= expr jmp_false expr JUMP_FORWARD expr COME_FROM
|
||||
conditional ::= expr jmp_false expr JUMP_ABSOLUTE expr
|
||||
expr ::= conditionalnot
|
||||
conditionalnot ::= expr jmp_true expr _jump expr COME_FROM
|
||||
|
||||
ret_expr ::= expr
|
||||
ret_expr ::= ret_and
|
||||
ret_expr ::= ret_or
|
||||
|
||||
ret_expr_or_cond ::= ret_expr
|
||||
ret_expr_or_cond ::= ret_cond
|
||||
ret_expr_or_cond ::= ret_cond_not
|
||||
|
||||
ret_and ::= expr JUMP_IF_FALSE_OR_POP ret_expr_or_cond COME_FROM
|
||||
ret_or ::= expr JUMP_IF_TRUE_OR_POP ret_expr_or_cond COME_FROM
|
||||
ret_cond ::= expr POP_JUMP_IF_FALSE expr RETURN_END_IF ret_expr_or_cond
|
||||
ret_cond_not ::= expr POP_JUMP_IF_TRUE expr RETURN_END_IF ret_expr_or_cond
|
||||
|
||||
stmt ::= return_lambda
|
||||
stmt ::= conditional_lambda
|
||||
|
||||
return_lambda ::= ret_expr RETURN_VALUE LAMBDA_MARKER
|
||||
conditional_lambda ::= expr jmp_false return_if_stmt return_stmt LAMBDA_MARKER
|
||||
|
||||
cmp ::= cmp_list
|
||||
cmp ::= compare
|
||||
compare ::= expr expr COMPARE_OP
|
||||
cmp_list ::= expr cmp_list1 ROT_TWO POP_TOP
|
||||
_come_from
|
||||
cmp_list1 ::= expr DUP_TOP ROT_THREE
|
||||
COMPARE_OP JUMP_IF_FALSE_OR_POP
|
||||
cmp_list1 COME_FROM
|
||||
cmp_list1 ::= expr DUP_TOP ROT_THREE
|
||||
COMPARE_OP jmp_false
|
||||
cmp_list1 _come_from
|
||||
cmp_list1 ::= expr DUP_TOP ROT_THREE
|
||||
COMPARE_OP JUMP_IF_FALSE_OR_POP
|
||||
cmp_list2 COME_FROM
|
||||
cmp_list1 ::= expr DUP_TOP ROT_THREE
|
||||
COMPARE_OP jmp_false
|
||||
cmp_list2 _come_from
|
||||
cmp_list2 ::= expr COMPARE_OP JUMP_FORWARD
|
||||
cmp_list2 ::= expr COMPARE_OP RETURN_VALUE
|
||||
mapexpr ::= BUILD_MAP kvlist
|
||||
|
||||
kvlist ::= kvlist kv
|
||||
kvlist ::= kvlist kv2
|
||||
kvlist ::= kvlist kv3
|
||||
kvlist ::=
|
||||
|
||||
kv ::= DUP_TOP expr ROT_TWO expr STORE_SUBSCR
|
||||
kv2 ::= DUP_TOP expr expr ROT_THREE STORE_SUBSCR
|
||||
kv3 ::= expr expr STORE_MAP
|
||||
|
||||
exprlist ::= exprlist expr
|
||||
exprlist ::= expr
|
||||
|
||||
nullexprlist ::=
|
||||
|
||||
expr32 ::= expr expr expr expr expr expr expr expr expr expr expr expr expr expr expr expr expr expr expr expr expr expr expr expr expr expr expr expr expr expr expr expr
|
||||
expr1024 ::= expr32 expr32 expr32 expr32 expr32 expr32 expr32 expr32 expr32 expr32 expr32 expr32 expr32 expr32 expr32 expr32 expr32 expr32 expr32 expr32 expr32 expr32 expr32 expr32 expr32 expr32 expr32 expr32 expr32 expr32 expr32 expr32
|
||||
'''
|
||||
|
||||
|
||||
def parse(p, tokens, customize):
|
||||
p.add_custom_rules(tokens, customize)
|
||||
ast = p.parse(tokens)
|
||||
@@ -76,20 +393,50 @@ def parse(p, tokens, customize):
|
||||
return ast
|
||||
|
||||
|
||||
def get_python_parser(version, debug_parser):
|
||||
"""
|
||||
Returns parser object for Python version 2 or 3
|
||||
depending on the parameter passed.
|
||||
def get_python_parser(version, debug_parser, compile_mode='exec'):
|
||||
"""Returns parser object for Python version 2 or 3, 3.2, 3.5on,
|
||||
etc., depending on the parameters passed. *compile_mode* is either
|
||||
'exec', 'eval', or 'single'. See
|
||||
https://docs.python.org/3.6/library/functions.html#compile for an
|
||||
explanation of the different modes.
|
||||
"""
|
||||
|
||||
if version < 3.0:
|
||||
import uncompyle6.parsers.parse2 as parse2
|
||||
p = parse2.Python2Parser(debug_parser)
|
||||
if compile_mode == 'exec':
|
||||
p = parse2.Python2Parser(debug_parser)
|
||||
else:
|
||||
p = parse2.Python2ParserSingle(debug_parser)
|
||||
else:
|
||||
import uncompyle6.parsers.parse3 as parse3
|
||||
p = parse3.Python3Parser(debug_parser)
|
||||
if version == 3.2:
|
||||
if compile_mode == 'exec':
|
||||
p = parse3.Python32Parser(debug_parser)
|
||||
else:
|
||||
p = parse3.Python32ParserSingle(debug_parser)
|
||||
elif version >= 3.5:
|
||||
if compile_mode == 'exec':
|
||||
p = parse3.Python35onParser(debug_parser)
|
||||
else:
|
||||
p = parse3.Python35onParserSingle(debug_parser)
|
||||
else:
|
||||
if compile_mode == 'exec':
|
||||
p = parse3.Python3Parser(debug_parser)
|
||||
else:
|
||||
p = parse3.Python3ParserSingle(debug_parser)
|
||||
p.version = version
|
||||
return p
|
||||
|
||||
class PythonParserSingle(PythonParser):
|
||||
def p_call_stmt(self, args):
|
||||
'''
|
||||
# single-mode compilation. Eval-mode interactive compilation
|
||||
# drops the last rule.
|
||||
|
||||
call_stmt ::= expr POP_TOP
|
||||
call_stmt ::= expr PRINT_EXPR
|
||||
'''
|
||||
|
||||
def python_parser(version, co, out=sys.stdout, showasm=False,
|
||||
parser_debug=PARSER_DEFAULT_DEBUG):
|
||||
assert iscode(co)
|
||||
@@ -100,12 +447,14 @@ def python_parser(version, co, out=sys.stdout, showasm=False,
|
||||
for t in tokens:
|
||||
print(t)
|
||||
|
||||
# For heavy grammar debugging
|
||||
# parser_debug = {'rules': True, 'transition': True, 'reduce' : True}
|
||||
p = get_python_parser(version, parser_debug)
|
||||
return parse(p, tokens, customize)
|
||||
|
||||
if __name__ == '__main__':
|
||||
def parse_test(co):
|
||||
from uncompyl6e import PYTHON_VERSION
|
||||
from uncompyle6 import PYTHON_VERSION
|
||||
ast = python_parser(PYTHON_VERSION, co, showasm=True)
|
||||
print(ast)
|
||||
return
|
||||
|
@@ -10,8 +10,8 @@ else:
|
||||
|
||||
|
||||
class AST(UserList):
|
||||
def __init__(self, type, kids=[]):
|
||||
self.type = intern(type)
|
||||
def __init__(self, kind, kids=[]):
|
||||
self.type = intern(kind)
|
||||
UserList.__init__(self, kids)
|
||||
|
||||
def isNone(self):
|
||||
@@ -28,7 +28,8 @@ class AST(UserList):
|
||||
else:
|
||||
return self.type == o
|
||||
|
||||
def __hash__(self): return hash(self.type)
|
||||
def __hash__(self):
|
||||
return hash(self.type)
|
||||
|
||||
def __repr__(self, indent=''):
|
||||
rv = str(self.type)
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user