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
45 Commits
release-py
...
3.6.7
Author | SHA1 | Date | |
---|---|---|---|
|
a4eaeea5b2 | ||
|
1141dfefc2 | ||
|
302a5d53d4 | ||
|
698a3073d0 | ||
|
e6adf822cc | ||
|
8c5acef792 | ||
|
7578253f7d | ||
|
9e193fd7cb | ||
|
ab6b12be56 | ||
|
5bd97aa756 | ||
|
5237d704fa | ||
|
a01285e4a9 | ||
|
1d7e8f1617 | ||
|
ced33a8f0b | ||
|
dc7f1ed0cc | ||
|
fc00d394ec | ||
|
e2baccb4e5 | ||
|
c99cf7a653 | ||
|
999eee4b5f | ||
|
9ca94717e0 | ||
|
b77efec36c | ||
|
17d07eaf00 | ||
|
538c2e7efd | ||
|
ebc22e32e6 | ||
|
4796fb9e70 | ||
|
ea81ac7202 | ||
|
2fd61b1016 | ||
|
ebd0eaa609 | ||
|
badfe5456f | ||
|
f117feb585 | ||
|
204b07c996 | ||
|
869e48877c | ||
|
7ed40d5f6e | ||
|
5c6365d8a1 | ||
|
42d3c4db61 | ||
|
f3b102600e | ||
|
f6a13302fb | ||
|
e8e7d2086d | ||
|
1367709399 | ||
|
3dcc20f6d7 | ||
|
5c83de830f | ||
|
451f0b55bb | ||
|
a5704cd462 | ||
|
52fbf1d6a7 | ||
|
0a3f951682 |
@@ -1,6 +1,7 @@
|
||||
version: 2
|
||||
jobs:
|
||||
build:
|
||||
working_directory: ~/rocky/python-uncompyle6
|
||||
parallelism: 1
|
||||
shell: /bin/bash --login
|
||||
# CircleCI 2.0 does not support environment variables that refer to each other the same way as 1.0 did.
|
||||
@@ -12,7 +13,7 @@ jobs:
|
||||
# To see the list of pre-built images that CircleCI provides for most common languages see
|
||||
# https://circleci.com/docs/2.0/circleci-images/
|
||||
docker:
|
||||
- image: circleci/python:2.7
|
||||
- image: circleci/python:3.6.9
|
||||
steps:
|
||||
# Machine Setup
|
||||
# If you break your build into multiple jobs with workflows, you will probably want to do the parts of this that are relevant in each
|
||||
@@ -22,6 +23,10 @@ jobs:
|
||||
# In many cases you can simplify this from what is generated here.
|
||||
# 'See docs on artifact collection here https://circleci.com/docs/2.0/artifacts/'
|
||||
- run: mkdir -p $CIRCLE_ARTIFACTS $CIRCLE_TEST_REPORTS
|
||||
# This is based on your 1.0 configuration file or project settings
|
||||
- run:
|
||||
working_directory: ~/rocky/python-uncompyle6
|
||||
command: pip install --user virtualenv && pip install --user nose && pip install --user pep8
|
||||
# Dependencies
|
||||
# This would typically go in either a build or a build-and-test job when using workflows
|
||||
# Restore the dependency cache
|
||||
@@ -31,9 +36,9 @@ jobs:
|
||||
# fallback to using the latest cache if no exact match is found
|
||||
- v2-dependencies-
|
||||
|
||||
# This is based on your 1.0 configuration file or project settings
|
||||
- run:
|
||||
command: sudo easy_install xdis spark-parser && sudo pip install -e . && sudo pip install -r requirements-dev.txt
|
||||
- run: pip install --user --upgrade setuptools
|
||||
- run: pip install --user -e .
|
||||
- run: pip install --user -r requirements-dev.txt
|
||||
|
||||
# Save dependency cache
|
||||
- save_cache:
|
||||
@@ -51,8 +56,8 @@ jobs:
|
||||
# Test
|
||||
# This would typically be a build job when using workflows, possibly combined with build
|
||||
# This is based on your 1.0 configuration file or project settings
|
||||
- run: sudo python ./setup.py develop && make check-2.7
|
||||
- run: cd test/stdlib && bash ./runtests.sh 'test_[p-z]*.py'
|
||||
- run: sudo python ./setup.py develop && make check-3.6
|
||||
- run: cd ./test/stdlib && bash ./runtests.sh 'test_[p-z]*.py'
|
||||
# Teardown
|
||||
# If you break your build into multiple jobs with workflows, you will probably want to do the parts of this that are relevant in each
|
||||
# Save test results
|
||||
|
11
.travis.yml
11
.travis.yml
@@ -1,7 +1,16 @@
|
||||
language: python
|
||||
|
||||
python:
|
||||
- 2.7 # this is a cheat here because travis doesn't do 2.4-2.6
|
||||
# - '3.5'
|
||||
# - '2.7'
|
||||
# - '3.4'
|
||||
- '3.6'
|
||||
- '3.8'
|
||||
|
||||
matrix:
|
||||
include:
|
||||
- python: '3.7'
|
||||
dist: xenial # required for Python >= 3.7 (travis-ci/travis-ci#9069)
|
||||
|
||||
install:
|
||||
- pip install -e .
|
||||
|
5
Makefile
5
Makefile
@@ -40,9 +40,8 @@ check-3.0 check-3.1 check-3.2 check-3.6:
|
||||
check-3.7: pytest
|
||||
$(MAKE) -C test check
|
||||
|
||||
#:Tests for Python 2.4-2.5 (don't have pytest)
|
||||
check-2.4 check-2.5:
|
||||
$(MAKE) -C test $@
|
||||
check-3.8:
|
||||
$(MAKE) -C test check
|
||||
|
||||
#:PyPy 2.6.1 PyPy 5.0.1, or PyPy 5.8.0-beta0
|
||||
# Skip for now
|
||||
|
19
NEWS.md
19
NEWS.md
@@ -1,11 +1,26 @@
|
||||
3.6.7: 2020-4-27 xdis again
|
||||
===========================
|
||||
|
||||
More upheaval in xdis which we need to track here.
|
||||
|
||||
3.6.6: 2020-4-20 Love in the time of Cholera
|
||||
============================================
|
||||
|
||||
The main reason for this release is an incompatablity bump in xdis which handles
|
||||
3.7 SipHash better.
|
||||
|
||||
* Go over "yield" as an expression precidence
|
||||
* Some small alignment with code in decompyle3 for "or" and "and" was done
|
||||
|
||||
|
||||
3.6.5: 2020-4-1 April Fool
|
||||
==========================
|
||||
|
||||
Back port some of the changes in decompile3 here which mostly helps 3.7 and 3.8 decompilation, although this may also help 3.6ish versions too.
|
||||
|
||||
- Handle nested `async for in for...` and Better async comprehension detection via `xdis`. Still more work is needed.
|
||||
- Handle nested `async for in for...` and better async comprehension detection via `xdis`. Still more work is needed.
|
||||
- include token number in listings when `-g` and there is a parser error
|
||||
- remove unneded `Makefile`s now that remake 4.3+1.5dbg is a thing that has `-c`
|
||||
- remove unneeded `Makefile`s now that remake 4.3+1.5dbg is a thing that has `-c`
|
||||
- Bug in finding annotations in functions with docstrings
|
||||
- Fix bug found by 2.4 sre_parse.py testing
|
||||
- Fix `transform` module's `ifelseif` bugs
|
||||
|
14
README.rst
14
README.rst
@@ -89,7 +89,8 @@ This uses setup.py, so it follows the standard Python routine:
|
||||
|
||||
::
|
||||
|
||||
$ pip install -e . # set up to run from source tree, or...
|
||||
$ pip install -e . # set up to run from source tree
|
||||
# Or if you want to install instead
|
||||
$ python setup.py install # may need sudo
|
||||
|
||||
A GNU makefile is also provided so :code:`make install` (possibly as root or
|
||||
@@ -100,7 +101,7 @@ Running Tests
|
||||
|
||||
::
|
||||
|
||||
$ make check
|
||||
make check
|
||||
|
||||
A GNU makefile has been added to smooth over setting running the right
|
||||
command, and running tests from fastest to slowest.
|
||||
@@ -251,11 +252,14 @@ See Also
|
||||
.. _uncompyle2: https://github.com/wibiti/uncompyle2
|
||||
.. _unpyc37: https://github.com/andrew-tavera/unpyc37
|
||||
.. _this: https://github.com/rocky/python-uncompyle6/wiki/Deparsing-technology-and-its-use-in-exact-location-reporting
|
||||
.. |buildstatus| image:: https://travis-ci.org/rocky/python-uncompyle6.svg :target: https://travis-ci.org/rocky/python-uncompyle6
|
||||
.. |packagestatus| image:: https://repology.org/badge/vertical-allrepos/python:uncompyle6.svg :target: https://repology.org/project/python:uncompyle6/versions
|
||||
.. |buildstatus| image:: https://travis-ci.org/rocky/python-uncompyle6.svg
|
||||
:target: https://travis-ci.org/rocky/python-uncompyle6
|
||||
.. |packagestatus| image:: https://repology.org/badge/vertical-allrepos/python:uncompyle6.svg
|
||||
:target: https://repology.org/project/python:uncompyle6/versions
|
||||
.. _PJOrion: http://www.koreanrandom.com/forum/topic/15280-pjorion-%D1%80%D0%B5%D0%B4%D0%B0%D0%BA%D1%82%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D0%B5-%D0%BA%D0%BE%D0%BC%D0%BF%D0%B8%D0%BB%D1%8F%D1%86%D0%B8%D1%8F-%D0%B4%D0%B5%D0%BA%D0%BE%D0%BC%D0%BF%D0%B8%D0%BB%D1%8F%D1%86%D0%B8%D1%8F-%D0%BE%D0%B1%D1%84
|
||||
.. _Deobfuscator: https://github.com/extremecoders-re/PjOrion-Deobfuscator
|
||||
.. _Py2EXE: https://en.wikipedia.org/wiki/Py2exe
|
||||
.. |Supported Python Versions| image:: https://img.shields.io/pypi/pyversions/uncompyle6.svg
|
||||
.. |Latest Version| image:: https://badge.fury.io/py/uncompyle6.svg :target: https://badge.fury.io/py/uncompyle6
|
||||
.. |Latest Version| image:: https://badge.fury.io/py/uncompyle6.svg
|
||||
:target: https://badge.fury.io/py/uncompyle6
|
||||
.. |Pypi Installs| image:: https://pepy.tech/badge/uncompyle6/month
|
||||
|
@@ -58,7 +58,7 @@ entry_points = {
|
||||
]}
|
||||
ftp_url = None
|
||||
install_requires = ["spark-parser >= 1.8.9, < 1.9.0",
|
||||
"xdis >= 4.2.4, < 4.3.0"]
|
||||
"xdis >= 4.5.1, < 4.6.0"]
|
||||
|
||||
license = "GPL3"
|
||||
mailing_list = "python-debugger@googlegroups.com"
|
||||
|
0
admin-tools/check-newer-versions.sh
Normal file → Executable file
0
admin-tools/check-newer-versions.sh
Normal file → Executable file
3
admin-tools/check-older-versions.sh
Normal file → Executable file
3
admin-tools/check-older-versions.sh
Normal file → Executable file
@@ -20,9 +20,8 @@ for version in $PYVERSIONS; do
|
||||
exit $?
|
||||
fi
|
||||
make clean && python setup.py develop
|
||||
if ! make check-short ; then
|
||||
if ! make check ; then
|
||||
exit $?
|
||||
fi
|
||||
echo === $version ===
|
||||
done
|
||||
make check
|
||||
|
@@ -55,9 +55,10 @@
|
||||
# Make packages and tag
|
||||
|
||||
$ . ./admin-tools/make-dist-older.sh
|
||||
$ pyenv local 3.8.1
|
||||
$ pyenv local 3.8.2
|
||||
$ twine check dist/uncompyle6-$VERSION*
|
||||
$ git tag release-python-2.4-$VERSION
|
||||
$ twine check dist/uncompyle6-$VERSION*
|
||||
$ . ./admin-tools/make-dist-newer.sh
|
||||
$ twine check dist/uncompyle6-$VERSION*
|
||||
|
||||
|
@@ -1,46 +0,0 @@
|
||||
git pull
|
||||
|
||||
Change version in uncompyle6/version.py
|
||||
source uncompyle6/version.py
|
||||
echo $VERSION
|
||||
git commit -m"Get ready for release $VERSION" .
|
||||
|
||||
Update ChangeLog:
|
||||
make ChangeLog
|
||||
|
||||
Update NEWS from ChangeLog
|
||||
make check
|
||||
|
||||
git commit --amend .
|
||||
|
||||
git push
|
||||
|
||||
Make sure pyenv is running
|
||||
# Pyenv
|
||||
|
||||
source admin-tools/check-newer-versions.sh
|
||||
|
||||
|
||||
# Switch to python-2.4 and build that first...
|
||||
source admin-tools/setup-python-2.4
|
||||
|
||||
rm ChangeLog
|
||||
git merge master
|
||||
|
||||
Update NEWS from master branch
|
||||
|
||||
git commit -m"Get ready for release $VERSION" .
|
||||
|
||||
source admin-tools/check-older-versions.sh
|
||||
source admin-tools/check-newer-versions.sh
|
||||
|
||||
make-dist-older.sh
|
||||
|
||||
git tag release-python-2.4-$VERSION
|
||||
|
||||
./make-dist-newer.sh
|
||||
|
||||
git tag release-$VERSION
|
||||
|
||||
|
||||
twine upload dist/uncompyle6-${VERSION}*
|
@@ -5,4 +5,4 @@ if [[ $0 == ${BASH_SOURCE[0]} ]] ; then
|
||||
echo "This script should be *sourced* rather than run directly through bash"
|
||||
exit 1
|
||||
fi
|
||||
export PYVERSIONS='3.5.9 3.6.10 2.6.9 3.3.7 2.7.17 3.2.6 3.1.5 3.4.10 3.7.7 3.8.2'
|
||||
export PYVERSIONS='3.5.9 3.6.10 2.6.9 3.3.7 2.7.18 3.2.6 3.1.5 3.4.10 3.7.7 3.8.2'
|
||||
|
@@ -6,4 +6,4 @@ if [[ $0 == ${BASH_SOURCE[0]} ]] ; then
|
||||
echo "This script should be *sourced* rather than run directly through bash"
|
||||
exit 1
|
||||
fi
|
||||
export PYVERSIONS='2.4.6 2.5.6'
|
||||
export PYVERSIONS='2.4.6 2.5.6 2.6.9'
|
||||
|
0
admin-tools/setup-master.sh
Normal file → Executable file
0
admin-tools/setup-master.sh
Normal file → Executable file
1
admin-tools/setup-python-2.4.sh
Normal file → Executable file
1
admin-tools/setup-python-2.4.sh
Normal file → Executable file
@@ -15,4 +15,3 @@ cd $fulldir/..
|
||||
git checkout python-2.4 && pyenv local $PYTHON_VERSION && git pull
|
||||
cd $owd
|
||||
rm -v */.python-version || true
|
||||
pyenv local $PYTHON_VERSION
|
||||
|
@@ -1,3 +0,0 @@
|
||||
#!/bin/bash
|
||||
cd $(dirname ${BASH_SOURCE[0]})/..
|
||||
git pull
|
@@ -53,6 +53,7 @@ install:
|
||||
# compiled extensions and are not provided as pre-built wheel packages,
|
||||
# pip will build them from source using the MSVC compiler matching the
|
||||
# target Python version and architecture
|
||||
- "%CMD_IN_ENV% pip install git+git://github.com/rocky/python-uncompyle6.git#egg=uncompyle6-3.6.6"
|
||||
- "%CMD_IN_ENV% pip install -r requirements.txt"
|
||||
|
||||
build_script:
|
||||
|
@@ -30,7 +30,7 @@ def list_comp():
|
||||
[y for y in range(3)]
|
||||
|
||||
def get_parsed_for_fn(fn):
|
||||
code = fn.func_code
|
||||
code = fn.__code__ if PYTHON3 else fn.func_code
|
||||
return deparse(code, version=PYTHON_VERSION)
|
||||
|
||||
def check_expect(expect, parsed, fn_name):
|
||||
|
@@ -20,7 +20,7 @@ def bug_loop(disassemble, tb=None):
|
||||
disassemble(tb)
|
||||
|
||||
def test_if_in_for():
|
||||
code = bug.func_code
|
||||
code = bug.__code__
|
||||
scan = get_scanner(PYTHON_VERSION)
|
||||
if 2.7 <= PYTHON_VERSION <= 3.0 and not IS_PYPY:
|
||||
scan.build_instructions(code)
|
||||
|
@@ -45,9 +45,6 @@ def test_grammar():
|
||||
expect_lhs.add("kvlist")
|
||||
expect_lhs.add("kv3")
|
||||
unused_rhs.add("dict")
|
||||
else:
|
||||
# NOTE: this may disappear
|
||||
expect_lhs.add("except_handler_else")
|
||||
|
||||
if PYTHON_VERSION < 3.7 and PYTHON_VERSION != 2.7:
|
||||
# NOTE: this may disappear
|
||||
|
@@ -8,8 +8,12 @@ from uncompyle6.semantics.consts import (
|
||||
|
||||
if PYTHON3:
|
||||
from io import StringIO
|
||||
def iteritems(d):
|
||||
return d.items()
|
||||
else:
|
||||
from StringIO import StringIO
|
||||
def iteritems(d):
|
||||
return d.iteritems()
|
||||
|
||||
from uncompyle6.semantics.pysource import (SourceWalker, deparse_code2str)
|
||||
|
||||
@@ -26,7 +30,7 @@ def test_template_engine():
|
||||
# FIXME: and so on...
|
||||
|
||||
from uncompyle6.semantics.consts import (
|
||||
TABLE_R, TABLE_DIRECT,
|
||||
TABLE_DIRECT, TABLE_R,
|
||||
)
|
||||
|
||||
from uncompyle6.semantics.fragments import (
|
||||
@@ -40,7 +44,7 @@ def test_tables():
|
||||
(TABLE_DIRECT, 'TABLE_DIRECT', False),
|
||||
(TABLE_R, 'TABLE_R', False),
|
||||
(TABLE_DIRECT_FRAGMENT, 'TABLE_DIRECT_FRAGMENT', True)):
|
||||
for k, entry in t.iteritems():
|
||||
for k, entry in iteritems(t):
|
||||
if k in skip_for_now:
|
||||
continue
|
||||
fmt = entry[0]
|
||||
|
@@ -1,4 +1,7 @@
|
||||
import pytest
|
||||
from uncompyle6 import PYTHON_VERSION, code_deparse
|
||||
pytestmark = pytest.mark.skip(PYTHON_VERSION < 2.7,
|
||||
reason="need at least Python 2.7")
|
||||
|
||||
if PYTHON_VERSION > 2.6:
|
||||
def test_single_mode():
|
||||
|
@@ -1,14 +1,13 @@
|
||||
from uncompyle6 import PYTHON_VERSION
|
||||
from uncompyle6.scanners.tok import Token
|
||||
|
||||
|
||||
def test_token():
|
||||
# Test token formatting of: LOAD_CONST None
|
||||
t = Token("LOAD_CONST", offset=0, attr=None, pattr=None, has_arg=True)
|
||||
expect = " 0 LOAD_CONST None"
|
||||
expect = "0 LOAD_CONST None"
|
||||
# print(t.format())
|
||||
assert t
|
||||
assert t.format() == expect
|
||||
assert t.format().strip() == expect.strip()
|
||||
|
||||
# Make sure equality testing of tokens ignores offset
|
||||
t2 = Token("LOAD_CONST", offset=2, attr=None, pattr=None, has_arg=True)
|
||||
@@ -17,8 +16,8 @@ def test_token():
|
||||
# Make sure formatting of: LOAD_CONST False. We assume False is the 0th index
|
||||
# of co_consts.
|
||||
t = Token("LOAD_CONST", offset=1, attr=False, pattr=False, has_arg=True)
|
||||
expect = " 1 LOAD_CONST False"
|
||||
assert t.format() == expect
|
||||
expect = "1 LOAD_CONST False"
|
||||
assert t.format().strip() == expect.strip()
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
2
pytest/testdata/if-2.7.right
vendored
2
pytest/testdata/if-2.7.right
vendored
@@ -9,4 +9,4 @@
|
||||
12 JUMP_FORWARD 0 'to 15'
|
||||
15_0 COME_FROM 12 '12'
|
||||
15 LOAD_CONST None
|
||||
18 RETURN_VALUE
|
||||
18 RETURN_VALUE
|
||||
|
2
pytest/testdata/ifelse-2.7.right
vendored
2
pytest/testdata/ifelse-2.7.right
vendored
@@ -12,4 +12,4 @@
|
||||
18 STORE_NAME 2 'd'
|
||||
21_0 COME_FROM 12 '12'
|
||||
21 LOAD_CONST None
|
||||
24 RETURN_VALUE
|
||||
24 RETURN_VALUE
|
||||
|
16
setup.py
16
setup.py
@@ -1,16 +1,16 @@
|
||||
#!/usr/bin/env python
|
||||
"""Setup script for the 'uncompyle6' distribution."""
|
||||
|
||||
import sys
|
||||
|
||||
"""Setup script for the 'uncompyle6' distribution."""
|
||||
|
||||
SYS_VERSION = sys.version_info[0:2]
|
||||
if not ((2, 4) <= SYS_VERSION <= (2, 7)):
|
||||
mess = "Python Release 2.4 .. 2.7 are supported in this code branch."
|
||||
if ((3, 2) <= SYS_VERSION <= (3, 8)):
|
||||
mess += ("\nFor your Python, version %s, use the master code/branch." %
|
||||
if not ((2, 6) <= SYS_VERSION <= (3, 9)):
|
||||
mess = "Python Release 2.6 .. 3.9 are supported in this code branch."
|
||||
if ((2, 4) <= SYS_VERSION <= (2, 7)):
|
||||
mess += ("\nFor your Python, version %s, use the python-2.4 code/branch." %
|
||||
sys.version[0:3])
|
||||
else:
|
||||
mess += ("\nThis package is not supported before Python 2.4. Your Python version is %s."
|
||||
elif SYS_VERSION < (2, 4):
|
||||
mess += ("\nThis package is not supported for Python version %s."
|
||||
% sys.version[0:3])
|
||||
print(mess)
|
||||
raise Exception(mess)
|
||||
|
@@ -1,55 +0,0 @@
|
||||
import re
|
||||
import unittest
|
||||
from uncompyle6 import PYTHON_VERSION, IS_PYPY # , PYTHON_VERSION
|
||||
from uncompyle6.parser import get_python_parser, python_parser
|
||||
|
||||
class TestGrammar(unittest.TestCase):
|
||||
def test_grammar(self):
|
||||
|
||||
def check_tokens(tokens, opcode_set):
|
||||
remain_tokens = set(tokens) - opcode_set
|
||||
remain_tokens = set([re.sub('_\d+$','', t) for t in remain_tokens])
|
||||
remain_tokens = set([re.sub('_CONT$','', t) for t in remain_tokens])
|
||||
remain_tokens = set(remain_tokens) - opcode_set
|
||||
self.assertEqual(remain_tokens, set([]),
|
||||
"Remaining tokens %s\n====\n%s" % (remain_tokens, p.dump_grammar()))
|
||||
|
||||
p = get_python_parser(PYTHON_VERSION, is_pypy=IS_PYPY)
|
||||
(lhs, rhs, tokens,
|
||||
right_recursive, dup_rhs) = p.check_sets()
|
||||
expect_lhs = set(['pos_arg', 'get_iter', 'attribute'])
|
||||
unused_rhs = set(['list', 'call', 'mkfunc',
|
||||
'mklambda',
|
||||
'unpack',])
|
||||
|
||||
expect_right_recursive = frozenset([('designList',
|
||||
('store', 'DUP_TOP', 'designList'))])
|
||||
expect_lhs.add('kwarg')
|
||||
|
||||
self.assertEqual(expect_lhs, set(lhs))
|
||||
self.assertEqual(unused_rhs, set(rhs))
|
||||
self.assertEqual(expect_right_recursive, right_recursive)
|
||||
|
||||
expect_dup_rhs = frozenset([('COME_FROM',), ('CONTINUE',), ('JUMP_ABSOLUTE',),
|
||||
('LOAD_CONST',),
|
||||
('JUMP_BACK',), ('JUMP_FORWARD',)])
|
||||
|
||||
reduced_dup_rhs = {}
|
||||
for k in dup_rhs:
|
||||
if k not in expect_dup_rhs:
|
||||
reduced_dup_rhs[k] = dup_rhs[k]
|
||||
pass
|
||||
pass
|
||||
for k in reduced_dup_rhs:
|
||||
print(k, reduced_dup_rhs[k])
|
||||
# assert not reduced_dup_rhs, reduced_dup_rhs
|
||||
|
||||
def test_dup_rule(self):
|
||||
import inspect
|
||||
python_parser(PYTHON_VERSION, inspect.currentframe().f_code,
|
||||
is_pypy=IS_PYPY,
|
||||
parser_debug={
|
||||
'dups': True, 'transition': False, 'reduce': False,
|
||||
'rules': False, 'errorstack': None, 'context': True})
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
@@ -30,7 +30,7 @@ check:
|
||||
$(MAKE) check-$(PYTHON_VERSION)
|
||||
|
||||
#: Run working tests from Python 2.6 or 2.7
|
||||
check-2.4 check-2.5 check-2.6 check-2.7: check-bytecode-2 check-bytecode-3 check-bytecode-1 check-native-short
|
||||
check-2.6 check-2.7: check-bytecode-2 check-bytecode-3 check-bytecode-1 check-native-short
|
||||
|
||||
#: Run working tests from Python 3.0
|
||||
check-3.0: check-bytecode
|
||||
@@ -72,10 +72,10 @@ check-3.7: check-bytecode
|
||||
$(PYTHON) test_pythonlib.py --bytecode-3.7-run --verify-run
|
||||
$(PYTHON) test_pythonlib.py --bytecode-3.7 --syntax-verify $(COMPILE)
|
||||
|
||||
# #: Run working tests from Python 3.8
|
||||
# check-3.8: check-bytecode
|
||||
# $(PYTHON) test_pythonlib.py --bytecode-3.8-run --verify-run
|
||||
# $(PYTHON) test_pythonlib.py --bytecode-3.8 --syntax-verify $(COMPILE)
|
||||
#: Run working tests from Python 3.8
|
||||
check-3.8: check-bytecode
|
||||
$(PYTHON) test_pythonlib.py --bytecode-3.8-run --verify-run
|
||||
$(PYTHON) test_pythonlib.py --bytecode-3.8 --syntax-verify $(COMPILE)
|
||||
|
||||
# FIXME
|
||||
#: this is called when running under pypy3.5-5.8.0, pypy2-5.6.0, or pypy3.6-7.3.0
|
||||
@@ -95,12 +95,19 @@ check-bytecode-2:
|
||||
--bytecode-2.5 --bytecode-2.6 --bytecode-2.7 --bytecode-pypy2.7
|
||||
|
||||
#: Check deparsing bytecode 3.x only
|
||||
# check-bytecode-3:
|
||||
# $(PYTHON) test_pythonlib.py \
|
||||
# --bytecode-3.0 \
|
||||
# --bytecode-3.1 --bytecode-3.2 --bytecode-3.3 \
|
||||
# --bytecode-3.4 --bytecode-3.5 --bytecode-3.6 \
|
||||
# --bytecode-3.7 \
|
||||
# --bytecode-pypy3.2 --bytecode-pypy3.6 --bytecode-3.8
|
||||
|
||||
# FIXME: Until we shaked out problems with xdis...
|
||||
check-bytecode-3:
|
||||
$(PYTHON) test_pythonlib.py --bytecode-3.0 \
|
||||
--bytecode-3.1 --bytecode-3.2 --bytecode-3.3 \
|
||||
$(PYTHON) test_pythonlib.py \
|
||||
--bytecode-3.4 --bytecode-3.5 --bytecode-3.6 \
|
||||
--bytecode-3.7 \
|
||||
--bytecode-pypy3.2 --bytecode-pypy3.6
|
||||
--bytecode-3.7 --bytecode-3.8
|
||||
|
||||
#: Check deparsing on selected bytecode 3.x
|
||||
check-bytecode-3-short:
|
||||
@@ -166,7 +173,6 @@ check-bytecode-2.3:
|
||||
|
||||
#: Check deparsing Python 2.4
|
||||
check-bytecode-2.4:
|
||||
$(PYTHON) test_pythonlib.py --bytecode-2.4-run --verify-run
|
||||
$(PYTHON) test_pythonlib.py --bytecode-2.4
|
||||
|
||||
#: Check deparsing Python 2.5
|
||||
@@ -295,20 +301,16 @@ check-bytecode-3.7:
|
||||
$(PYTHON) test_pythonlib.py --bytecode-3.7-run --verify-run
|
||||
$(PYTHON) test_pythonlib.py --bytecode-3.7 --syntax-verify
|
||||
|
||||
# #: Check deparsing Python 3.8
|
||||
# check-bytecode-3.8:
|
||||
# $(PYTHON) test_pythonlib.py --bytecode-3.8-run --verify-run
|
||||
# $(PYTHON) test_pythonlib.py --bytecode-3.8 --syntax-verify
|
||||
#: Check deparsing Python 3.8
|
||||
check-bytecode-3.8:
|
||||
$(PYTHON) test_pythonlib.py --bytecode-3.8-run --verify-run
|
||||
$(PYTHON) test_pythonlib.py --bytecode-3.8 --syntax-verify
|
||||
|
||||
#: short tests for bytecodes only for this version of Python
|
||||
check-native-short:
|
||||
$(PYTHON) test_pythonlib.py --bytecode-$(PYTHON_VERSION) --syntax-verify $(COMPILE)
|
||||
$(PYTHON) test_pythonlib.py --bytecode-$(PYTHON_VERSION)-run --verify-run $(COMPILE)
|
||||
|
||||
#: Run longer Python 2.6's lib files known to be okay
|
||||
check-2.4-ok:
|
||||
$(PYTHON) test_pythonlib.py --ok-2.4 --verify $(COMPILE)
|
||||
|
||||
#: Run longer Python 2.6's lib files known to be okay
|
||||
check-2.6-ok:
|
||||
$(PYTHON) test_pythonlib.py --ok-2.6 --syntax-verify $(COMPILE)
|
||||
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
test/bytecode_2.4/02_slice.pyc
Normal file
BIN
test/bytecode_2.4/02_slice.pyc
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
test/bytecode_2.4/10_for.pyc
Normal file
BIN
test/bytecode_2.4/10_for.pyc
Normal file
Binary file not shown.
BIN
test/bytecode_2.4/10_mixed_boolean.pyc
Normal file
BIN
test/bytecode_2.4/10_mixed_boolean.pyc
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
test/bytecode_2.6/02_slice.pyc
Normal file
BIN
test/bytecode_2.6/02_slice.pyc
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
test/bytecode_2.6/10_for.pyc
Normal file
BIN
test/bytecode_2.6/10_for.pyc
Normal file
Binary file not shown.
BIN
test/bytecode_2.6/10_mixed_boolean.pyc
Normal file
BIN
test/bytecode_2.6/10_mixed_boolean.pyc
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
test/bytecode_2.7/10_del.pyc
Normal file
BIN
test/bytecode_2.7/10_del.pyc
Normal file
Binary file not shown.
BIN
test/bytecode_3.1/01_ops.pyc
Normal file
BIN
test/bytecode_3.1/01_ops.pyc
Normal file
Binary file not shown.
BIN
test/bytecode_3.2/01_ops.pyc
Normal file
BIN
test/bytecode_3.2/01_ops.pyc
Normal file
Binary file not shown.
@@ -1,8 +1,9 @@
|
||||
#!/usr/bin/env python
|
||||
# Mode: -*- python -*-
|
||||
#
|
||||
# Copyright (c) 2015, 2017 by Rocky Bernstein <rb@dustyfeet.com>
|
||||
# Copyright (c) 2015 by Rocky Bernstein <rb@dustyfeet.com>
|
||||
#
|
||||
from __future__ import print_function
|
||||
|
||||
|
||||
import dis, os.path
|
||||
|
@@ -34,9 +34,10 @@ else
|
||||
fi
|
||||
|
||||
MAIN="test_pyenvlib.py"
|
||||
|
||||
USER=${USER:-rocky}
|
||||
EMAIL=${EMAIL:-rb@dustyfeet.com}
|
||||
WHAT="uncompyle6 2.4 ${MAIN}"
|
||||
WHAT="uncompyle6 ${MAIN}"
|
||||
MAX_TESTS=${MAX_TESTS:-800}
|
||||
export BATCH=1
|
||||
|
||||
@@ -44,7 +45,7 @@ typeset -i RUN_STARTTIME=$(date +%s)
|
||||
|
||||
# PYVERSIONS="3.5.6"
|
||||
MAILBODY=/tmp/${MAIN}-mailbody-$$.txt
|
||||
# for VERSION in 2.4.6 2.5.9 ; do
|
||||
# for VERSION in 3.3.7 ; do
|
||||
for VERSION in $PYVERSIONS ; do
|
||||
typeset -i rc=0
|
||||
LOGFILE=/tmp/${MAIN}-$VERSION-$$.log
|
||||
@@ -66,7 +67,9 @@ for VERSION in $PYVERSIONS ; do
|
||||
MAX_TESTS=800
|
||||
;;
|
||||
3.6.10 )
|
||||
MAX_TESTS=1300 # about 2139 exist
|
||||
# MAX_TESTS=1300 # about 2139 exist
|
||||
# fails on _pyio.cpython-36.opt-1.pyc
|
||||
MAX_TESTS=34
|
||||
;;
|
||||
2.4.6 )
|
||||
MAX_TESTS=600
|
||||
|
@@ -1,6 +1,7 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
from uncompyle6 import uncompyle
|
||||
from __future__ import print_function
|
||||
|
||||
from uncompyle6.main import decompile
|
||||
from xdis.magics import sysinfo2float
|
||||
import sys, inspect
|
||||
|
@@ -1,7 +0,0 @@
|
||||
# From 2.4 test_array.py
|
||||
# In Python 2.4 and earlier "yield" is not valid and instead
|
||||
# we must use "yield None". Bug was not adding "None"
|
||||
|
||||
def yield_bug():
|
||||
yield None
|
||||
return
|
@@ -1,19 +0,0 @@
|
||||
# From 2.4 test_sax.py
|
||||
# Bug was distinguishing try from try/else
|
||||
|
||||
def verify_empty_attrs():
|
||||
gvqk = 3
|
||||
try:
|
||||
gvk = 1/0
|
||||
except ZeroDivisionError:
|
||||
gvk = 1
|
||||
|
||||
try:
|
||||
gvqk = 0
|
||||
except KeyError:
|
||||
gvqk = 1
|
||||
|
||||
# If try/else was used above the return will be 4
|
||||
return gvk + gvqk
|
||||
|
||||
assert 1 == verify_empty_attrs()
|
87
test/simple_source/bug37/04_grammar.py
Normal file
87
test/simple_source/bug37/04_grammar.py
Normal file
@@ -0,0 +1,87 @@
|
||||
# From test_grammar.py
|
||||
# RUNNABLE!
|
||||
def check_syntax_error(statement):
|
||||
try:
|
||||
compile(statement, '<test string>', 'exec')
|
||||
except SyntaxError:
|
||||
return
|
||||
assert False
|
||||
|
||||
def test_yield():
|
||||
# Requires parentheses as call argument
|
||||
def g():
|
||||
f((yield 1), 1)
|
||||
def g():
|
||||
f((yield from ()))
|
||||
def g():
|
||||
f((yield from ()), 1)
|
||||
def g():
|
||||
f((yield 1))
|
||||
|
||||
# Allowed as standalone statement
|
||||
def g():
|
||||
yield 1
|
||||
|
||||
def g():
|
||||
yield from ()
|
||||
|
||||
# Allowed as RHS of assignment
|
||||
def g():
|
||||
x = yield 1
|
||||
|
||||
def g():
|
||||
x = yield from ()
|
||||
|
||||
# Ordinary yield accepts implicit tuples
|
||||
def g():
|
||||
yield 1, 1
|
||||
|
||||
def g():
|
||||
x = yield 1, 1
|
||||
|
||||
# 'yield from' does not
|
||||
check_syntax_error("def g(): yield from (), 1")
|
||||
check_syntax_error("def g(): x = yield from (), 1")
|
||||
# Requires parentheses as subexpression
|
||||
def g():
|
||||
1, (yield 1)
|
||||
|
||||
def g():
|
||||
1, (yield from ())
|
||||
|
||||
check_syntax_error("def g(): 1, yield 1")
|
||||
check_syntax_error("def g(): 1, yield from ()")
|
||||
# Requires parentheses as call argument
|
||||
def g():
|
||||
f((yield 1))
|
||||
|
||||
def g():
|
||||
f((yield 1), 1)
|
||||
|
||||
def g():
|
||||
f((yield from ()))
|
||||
|
||||
def g():
|
||||
f((yield from ()), 1)
|
||||
|
||||
check_syntax_error("def g(): f(yield 1)")
|
||||
check_syntax_error("def g(): f(yield 1, 1)")
|
||||
check_syntax_error("def g(): f(yield from ())")
|
||||
check_syntax_error("def g(): f(yield from (), 1)")
|
||||
# Not allowed at top level
|
||||
check_syntax_error("yield")
|
||||
check_syntax_error("yield from")
|
||||
# Not allowed at class scope
|
||||
check_syntax_error("class foo:yield 1")
|
||||
check_syntax_error("class foo:yield from ()")
|
||||
# Check annotation refleak on SyntaxError
|
||||
check_syntax_error("def g(a:(yield)): pass")
|
||||
|
||||
test_yield()
|
||||
|
||||
# From test_types.py
|
||||
# Bug was needing parens around (yield 2)
|
||||
def gen_func():
|
||||
yield 1
|
||||
return (yield 2)
|
||||
gen = gen_func()
|
@@ -5,7 +5,6 @@ SKIP_TESTS=(
|
||||
[test_ftplib.py]=1 # FIXME: Works on c90ff51
|
||||
[test_slice.py]=1 # FIXME: Works on c90ff51
|
||||
[test_sort.py]=1 # FIXME: Works on c90ff51
|
||||
[test_strftime.py]=1 # FIXME: Works on c90ff51
|
||||
[test_timeit.py]=1 # FIXME: Works on c90ff51
|
||||
[test_os.py]=1 # parse error FIXME: Works on c90ff51
|
||||
|
||||
|
@@ -1,10 +1,14 @@
|
||||
SKIP_TESTS=(
|
||||
[test_time.py]=1 # FIXME: works on uncompyle6?
|
||||
[test_mimetypes.py]=1 # parse error. decompile3 works. Release 3.6.4 works?
|
||||
[test_time.py]=1 # FIXME: parse eror. decompyle3 works. Release 3.6.4 works?
|
||||
[test_aifc.py]=1 # parse error; decompile3 works
|
||||
|
||||
[test_doctest2.py]=1 # test failures release 3.6.4 works?
|
||||
[test_finalization.py]=1 # test failures release 3.6.4 works?
|
||||
[test_urllib2.py]=1 # FIXME: works on uncompyle6?
|
||||
[test_zipimport.py]=1 # FIXME: works on uncompyle6
|
||||
|
||||
[test___all__.py]=1 # it fails on its own
|
||||
[test_aifc.py]=1 # parse error
|
||||
[test_argparse.py]=1 #- it fails on its own
|
||||
[test_array.py]=1 #- parse error
|
||||
[test_asdl_parser.py]=1 # it fails on its own
|
||||
@@ -76,6 +80,7 @@ SKIP_TESTS=(
|
||||
[test_difflib.py]=1 # parse error
|
||||
[test_dis.py]=1 # We change line numbers - duh!
|
||||
[test_doctest.py]=1 # parse error
|
||||
[test_doctest2.py]=1 # test faiures relesae 3.6.4 works?
|
||||
[test_docxmlrpc.py]=1
|
||||
[test_dtrace.py]=1 # parse error
|
||||
[test_dummy_thread.py]=1 # parse error
|
||||
@@ -91,6 +96,7 @@ SKIP_TESTS=(
|
||||
[test_exceptions.py]=1 # parse error
|
||||
|
||||
[test_faulthandler.py]=1 # takes too long
|
||||
[test_file_eintr.py]=1 # too long to run test; works on 3.7.7
|
||||
[test_fcntl.py]=1
|
||||
[test_filecmp.py]=1 # parse error
|
||||
[test_fileinput.py]=1
|
||||
|
@@ -20,7 +20,8 @@ Step 2: Run the test:
|
||||
test_pyenvlib --mylib --verify # decompile verify 'mylib'
|
||||
"""
|
||||
|
||||
from uncompyle6 import main, PYTHON3
|
||||
from __future__ import print_function
|
||||
|
||||
import os, time, re, shutil, sys
|
||||
from fnmatch import fnmatch
|
||||
|
||||
|
@@ -27,6 +27,8 @@ Step 2: Run the test:
|
||||
test_pythonlib.py --mylib --verify # decompile verify 'mylib'
|
||||
"""
|
||||
|
||||
from __future__ import print_function
|
||||
|
||||
import getopt, os, py_compile, sys, shutil, tempfile, time
|
||||
|
||||
from uncompyle6 import PYTHON_VERSION
|
||||
@@ -155,10 +157,11 @@ def do_tests(src_dir, obj_patterns, target_dir, opts):
|
||||
if opts["do_compile"]:
|
||||
compiled_version = opts["compiled_version"]
|
||||
if compiled_version and PYTHON_VERSION != compiled_version:
|
||||
sys.stderr.write("Not compiling: "
|
||||
"desired Python version is %s "
|
||||
"but we are running %s" %
|
||||
(compiled_version, PYTHON_VERSION))
|
||||
print(
|
||||
"Not compiling: desired Python version is %s but we are running %s"
|
||||
% (compiled_version, PYTHON_VERSION),
|
||||
file=sys.stderr,
|
||||
)
|
||||
else:
|
||||
for root, dirs, basenames in os.walk(src_dir):
|
||||
file_matches(files, root, basenames, PY)
|
||||
@@ -176,8 +179,10 @@ def do_tests(src_dir, obj_patterns, target_dir, opts):
|
||||
file_matches(files, dirname, basenames, obj_patterns)
|
||||
|
||||
if not files:
|
||||
sys.stderr.write("Didn't come up with any files to test! "
|
||||
"Try with --compile?")
|
||||
print(
|
||||
"Didn't come up with any files to test! Try with --compile?",
|
||||
file=sys.stderr,
|
||||
)
|
||||
exit(1)
|
||||
|
||||
os.chdir(cwd)
|
||||
@@ -192,8 +197,8 @@ def do_tests(src_dir, obj_patterns, target_dir, opts):
|
||||
pass
|
||||
|
||||
print(time.ctime())
|
||||
print "Source directory: ", src_dir
|
||||
print "Output directory: ", target_dir
|
||||
print("Source directory: ", src_dir)
|
||||
print("Output directory: ", target_dir)
|
||||
try:
|
||||
_, _, failed_files, failed_verify = main(
|
||||
src_dir, target_dir, files, [], do_verify=opts["do_verify"]
|
||||
@@ -280,13 +285,13 @@ if __name__ == "__main__":
|
||||
if os.path.isdir(src_dir):
|
||||
checked_dirs.append([src_dir, pattern, target_dir])
|
||||
else:
|
||||
sys.stderr.write("Can't find directory %s. Skipping" % src_dir)
|
||||
print("Can't find directory %s. Skipping" % src_dir, file=sys.stderr)
|
||||
continue
|
||||
last_compile_version = compiled_version
|
||||
pass
|
||||
|
||||
if not checked_dirs:
|
||||
sys.stderr.write("No directories found to check\n")
|
||||
print("No directories found to check", file=sys.stderr)
|
||||
sys.exit(1)
|
||||
|
||||
test_opts["compiled_version"] = last_compile_version
|
||||
|
1
uncompyle6/.gitignore
vendored
1
uncompyle6/.gitignore
vendored
@@ -1 +0,0 @@
|
||||
/.python-version
|
@@ -3,6 +3,7 @@
|
||||
#
|
||||
# Copyright (c) 2015-2016, 2018 by Rocky Bernstein <rb@dustyfeet.com>
|
||||
#
|
||||
from __future__ import print_function
|
||||
import sys, os, getopt
|
||||
|
||||
from uncompyle6.disas import disassemble_file
|
||||
@@ -12,8 +13,8 @@ program, ext = os.path.splitext(os.path.basename(__file__))
|
||||
|
||||
__doc__ = """
|
||||
Usage:
|
||||
%s [OPTIONS]... FILE
|
||||
%s [--help | -h | -V | --version]
|
||||
{0} [OPTIONS]... FILE
|
||||
{0} [--help | -h | -V | --version]
|
||||
|
||||
Disassemble FILE with the instruction mangling that is done to
|
||||
assist uncompyle6 in parsing the instruction stream. For example
|
||||
@@ -22,9 +23,9 @@ BUILD_LIST have argument counts appended to the instruction name, and
|
||||
COME_FROM instructions are inserted into the instruction stream.
|
||||
|
||||
Examples:
|
||||
%s foo.pyc
|
||||
%s foo.py # same thing as above but find the file
|
||||
%s foo.pyc bar.pyc # disassemble foo.pyc and bar.pyc
|
||||
{0} foo.pyc
|
||||
{0} foo.py # same thing as above but find the file
|
||||
{0} foo.pyc bar.pyc # disassemble foo.pyc and bar.pyc
|
||||
|
||||
See also `pydisasm' from the `xdis' package.
|
||||
|
||||
@@ -32,7 +33,7 @@ Options:
|
||||
-V | --version show version and stop
|
||||
-h | --help show this message
|
||||
|
||||
""" % ((program,) * 5)
|
||||
""".format(program)
|
||||
|
||||
PATTERNS = ('*.pyc', '*.pyo')
|
||||
|
||||
@@ -41,15 +42,15 @@ def main():
|
||||
Type -h for for full help.""" % program
|
||||
|
||||
if len(sys.argv) == 1:
|
||||
sys.stderr.write("No file(s) given\n")
|
||||
sys.stderr.write(Usage_short)
|
||||
print("No file(s) given", file=sys.stderr)
|
||||
print(Usage_short, file=sys.stderr)
|
||||
sys.exit(1)
|
||||
|
||||
try:
|
||||
opts, files = getopt.getopt(sys.argv[1:], 'hVU',
|
||||
['help', 'version', 'uncompyle6'])
|
||||
except getopt.GetoptError(e):
|
||||
sys.stderr.write('%s: %s' % (os.path.basename(sys.argv[0]), e))
|
||||
except getopt.GetoptError as e:
|
||||
print('%s: %s' % (os.path.basename(sys.argv[0]), e), file=sys.stderr)
|
||||
sys.exit(-1)
|
||||
|
||||
for opt, val in opts:
|
||||
@@ -61,14 +62,15 @@ Type -h for for full help.""" % program
|
||||
sys.exit(0)
|
||||
else:
|
||||
print(opt)
|
||||
sys.stderr.write(Usage_short)
|
||||
print(Usage_short, file=sys.stderr)
|
||||
sys.exit(1)
|
||||
|
||||
for file in files:
|
||||
if os.path.exists(files[0]):
|
||||
disassemble_file(file, sys.stdout)
|
||||
else:
|
||||
sys.stderr.write("Can't read %s - skipping\n" % files[0])
|
||||
print("Can't read %s - skipping" % files[0],
|
||||
file=sys.stderr)
|
||||
pass
|
||||
pass
|
||||
return
|
||||
|
@@ -4,6 +4,7 @@
|
||||
# Copyright (c) 2015-2017, 2019 by Rocky Bernstein
|
||||
# Copyright (c) 2000-2002 by hartmut Goebel <h.goebel@crazy-compilers.com>
|
||||
#
|
||||
from __future__ import print_function
|
||||
import sys, os, getopt, time
|
||||
|
||||
program = 'uncompyle6'
|
||||
@@ -70,9 +71,13 @@ def usage():
|
||||
|
||||
|
||||
def main_bin():
|
||||
if not (sys.version_info[0:2] in ((2, 4), (2, 5), (2, 6), (2, 7))):
|
||||
sys.stderr.write('Error: this branch of %s requires Python 2.4, 2.5, 2.6 or 2.7'
|
||||
% program)
|
||||
if not (sys.version_info[0:2] in ((2, 6), (2, 7), (3, 0),
|
||||
(3, 1), (3, 2), (3, 3),
|
||||
(3, 4), (3, 5), (3, 6),
|
||||
(3, 7), (3, 8)
|
||||
)):
|
||||
print('Error: %s requires Python 2.6-3.8' % program,
|
||||
file=sys.stderr)
|
||||
sys.exit(-1)
|
||||
|
||||
do_verify = recurse_dirs = False
|
||||
@@ -90,9 +95,8 @@ def main_bin():
|
||||
'fragments verify verify-run version '
|
||||
'syntax-verify '
|
||||
'showgrammar encoding='.split(' '))
|
||||
except getopt.GetoptError, e:
|
||||
sys.stderr.write('%s: %s\n' %
|
||||
(os.path.basename(sys.argv[0]), e))
|
||||
except getopt.GetoptError as e:
|
||||
print('%s: %s' % (os.path.basename(sys.argv[0]), e), file=sys.stderr)
|
||||
sys.exit(-1)
|
||||
|
||||
options = {}
|
||||
@@ -146,7 +150,7 @@ def main_bin():
|
||||
elif opt == '--encoding':
|
||||
options['source_encoding'] = val
|
||||
else:
|
||||
sys.stderr.write(opt)
|
||||
print(opt, file=sys.stderr)
|
||||
usage()
|
||||
|
||||
# expand directory if specified
|
||||
@@ -170,8 +174,8 @@ def main_bin():
|
||||
sb_len = len( os.path.join(src_base, '') )
|
||||
pyc_paths = [f[sb_len:] for f in pyc_paths]
|
||||
|
||||
if not pyc_paths:
|
||||
sys.stderr.write("No files given\n")
|
||||
if not pyc_paths and not source_paths:
|
||||
print("No input files given to decompile", file=sys.stderr)
|
||||
usage()
|
||||
|
||||
if outfile == '-':
|
||||
|
@@ -1,4 +1,4 @@
|
||||
# Copyright (c) 2015-2016, 2818-2019 by Rocky Bernstein
|
||||
# Copyright (c) 2015-2016, 2818-2020 by Rocky Bernstein
|
||||
# Copyright (c) 2005 by Dan Pascu <dan@windowmaker.org>
|
||||
# Copyright (c) 2000-2002 by hartmut Goebel <h.goebel@crazy-compilers.com>
|
||||
# Copyright (c) 1999 John Aycock
|
||||
@@ -29,10 +29,12 @@ Second, we need structured instruction information for the
|
||||
want to run on earlier Python versions.
|
||||
"""
|
||||
|
||||
from __future__ import print_function
|
||||
|
||||
import sys
|
||||
from collections import deque
|
||||
|
||||
from xdis.code import iscode
|
||||
from xdis import iscode
|
||||
from xdis.load import check_object_path, load_module
|
||||
from uncompyle6.scanner import get_scanner
|
||||
|
||||
@@ -46,9 +48,9 @@ def disco(version, co, out=None, is_pypy=False):
|
||||
|
||||
# store final output stream for case of error
|
||||
real_out = out or sys.stdout
|
||||
real_out.write("# Python %s\n" % version)
|
||||
print("# Python %s" % version, file=real_out)
|
||||
if co.co_filename:
|
||||
real_out.write("# Embedded file name: %s\n" % co.co_filename)
|
||||
print("# Embedded file name: %s" % co.co_filename, file=real_out)
|
||||
|
||||
scanner = get_scanner(version, is_pypy=is_pypy)
|
||||
|
||||
@@ -60,15 +62,18 @@ def disco_loop(disasm, queue, real_out):
|
||||
while len(queue) > 0:
|
||||
co = queue.popleft()
|
||||
if co.co_name != "<module>":
|
||||
real_out.write("\n# %s line %d of %s\n" %
|
||||
(co.co_name, co.co_firstlineno, co.co_filename))
|
||||
print(
|
||||
"\n# %s line %d of %s"
|
||||
% (co.co_name, co.co_firstlineno, co.co_filename),
|
||||
file=real_out,
|
||||
)
|
||||
tokens, customize = disasm(co)
|
||||
for t in tokens:
|
||||
if iscode(t.pattr):
|
||||
queue.append(t.pattr)
|
||||
elif iscode(t.attr):
|
||||
queue.append(t.attr)
|
||||
real_out.write(t)
|
||||
print(t, file=real_out)
|
||||
pass
|
||||
pass
|
||||
|
||||
@@ -95,7 +100,9 @@ def disassemble_file(filename, outstream=None):
|
||||
try to find the corresponding compiled object.
|
||||
"""
|
||||
filename = check_object_path(filename)
|
||||
(version, timestamp, magic_int, co, is_pypy, source_size) = load_module(filename)
|
||||
(version, timestamp, magic_int, co, is_pypy, source_size, sip_hash) = load_module(
|
||||
filename
|
||||
)
|
||||
if type(co) == list:
|
||||
for con in co:
|
||||
disco(version, con, outstream)
|
||||
|
@@ -15,17 +15,17 @@
|
||||
|
||||
from collections import deque
|
||||
|
||||
from xdis.code import iscode
|
||||
from xdis import iscode
|
||||
from xdis.load import load_file, load_module
|
||||
from xdis.main import get_opcode
|
||||
from xdis.bytecode import Bytecode, findlinestarts, offset2line
|
||||
|
||||
def line_number_mapping(pyc_filename, src_filename):
|
||||
(version, timestamp, magic_int, code1, is_pypy,
|
||||
source_size) = load_module(pyc_filename)
|
||||
source_size, sip_hash) = load_module(pyc_filename)
|
||||
try:
|
||||
code2 = load_file(src_filename)
|
||||
except SyntaxError, e:
|
||||
except SyntaxError as e:
|
||||
return str(e)
|
||||
|
||||
queue = deque([code1, code2])
|
||||
|
@@ -12,10 +12,11 @@
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
import datetime, os, subprocess, sys
|
||||
from __future__ import print_function
|
||||
import datetime, py_compile, os, subprocess, sys, tempfile
|
||||
|
||||
from uncompyle6 import verify, IS_PYPY, PYTHON_VERSION
|
||||
from xdis.code import iscode
|
||||
from xdis import iscode
|
||||
from xdis.magics import sysinfo2float
|
||||
from uncompyle6.disas import check_object_path
|
||||
from uncompyle6.semantics import pysource
|
||||
@@ -40,7 +41,11 @@ def _get_outstream(outfile):
|
||||
os.makedirs(dir)
|
||||
except OSError:
|
||||
pass
|
||||
return open(outfile, 'wb')
|
||||
if PYTHON_VERSION < 3.0:
|
||||
return open(outfile, mode="wb")
|
||||
else:
|
||||
return open(outfile, mode="w", encoding="utf-8")
|
||||
|
||||
|
||||
def decompile(
|
||||
bytecode_version,
|
||||
@@ -78,44 +83,34 @@ def decompile(
|
||||
|
||||
assert iscode(co)
|
||||
|
||||
if is_pypy:
|
||||
co_pypy_str = "PyPy "
|
||||
else:
|
||||
co_pypy_str = ""
|
||||
|
||||
if IS_PYPY:
|
||||
run_pypy_str = "PyPy "
|
||||
else:
|
||||
run_pypy_str = ""
|
||||
|
||||
if magic_int:
|
||||
m = str(magic_int)
|
||||
else:
|
||||
m = ""
|
||||
|
||||
co_pypy_str = "PyPy " if is_pypy else ""
|
||||
run_pypy_str = "PyPy " if IS_PYPY else ""
|
||||
sys_version_lines = sys.version.split("\n")
|
||||
if source_encoding:
|
||||
write("# -*- coding: %s -*-" % source_encoding)
|
||||
write(
|
||||
"# uncompyle6 version %s\n"
|
||||
"# %sPython bytecode %s%s\n# Decompiled from: %sPython %s" %
|
||||
(VERSION,
|
||||
co_pypy_str,
|
||||
bytecode_version,
|
||||
" (%s)" % m, run_pypy_str,
|
||||
"\n# ".join(sys_version_lines),
|
||||
)
|
||||
"# %sPython bytecode %s%s\n# Decompiled from: %sPython %s"
|
||||
% (
|
||||
VERSION,
|
||||
co_pypy_str,
|
||||
bytecode_version,
|
||||
" (%s)" % str(magic_int) if magic_int else "",
|
||||
run_pypy_str,
|
||||
"\n# ".join(sys_version_lines),
|
||||
)
|
||||
)
|
||||
if bytecode_version >= 3.0:
|
||||
write("# Warning: this version has problems handling the Python 3 byte type in contants properly.\n")
|
||||
if PYTHON_VERSION < 3.0 and bytecode_version >= 3.0:
|
||||
write(
|
||||
'# Warning: this version has problems handling the Python 3 "byte" type in constants properly.\n'
|
||||
)
|
||||
|
||||
if co.co_filename:
|
||||
write("# Embedded file name: %s" % co.co_filename,)
|
||||
if timestamp:
|
||||
write("# Compiled at: %s" %
|
||||
datetime.datetime.fromtimestamp(timestamp))
|
||||
write("# Compiled at: %s" % datetime.datetime.fromtimestamp(timestamp))
|
||||
if source_size:
|
||||
real_out.write("# Size of source mod 2**32: %d bytes\n" %
|
||||
source_size)
|
||||
write("# Size of source mod 2**32: %d bytes" % source_size)
|
||||
|
||||
debug_opts = {"asm": showasm, "ast": showast, "grammar": showgrammar}
|
||||
|
||||
@@ -150,7 +145,7 @@ def decompile(
|
||||
)
|
||||
pass
|
||||
return deparsed
|
||||
except pysource.SourceWalkerError, e:
|
||||
except pysource.SourceWalkerError as e:
|
||||
# deparsing failed
|
||||
raise pysource.SourceWalkerError(str(e))
|
||||
|
||||
@@ -188,7 +183,7 @@ def decompile_file(
|
||||
|
||||
filename = check_object_path(filename)
|
||||
code_objects = {}
|
||||
(version, timestamp, magic_int, co, is_pypy, source_size) = load_module(
|
||||
(version, timestamp, magic_int, co, is_pypy, source_size, sip_hash) = load_module(
|
||||
filename, code_objects
|
||||
)
|
||||
|
||||
@@ -293,16 +288,20 @@ def main(
|
||||
prefix = prefix[: -len(".py")]
|
||||
|
||||
# Unbuffer output if possible
|
||||
if sys.stdout.isatty():
|
||||
buffering = -1
|
||||
buffering = -1 if sys.stdout.isatty() else 0
|
||||
if PYTHON_VERSION >= 3.5:
|
||||
t = tempfile.NamedTemporaryFile(
|
||||
mode="w+b", buffering=buffering, suffix=".py", prefix=prefix
|
||||
)
|
||||
else:
|
||||
buffering = 0
|
||||
sys.stdout = os.fdopen(sys.stdout.fileno(), 'w', buffering)
|
||||
if PYTHON_VERSION > 2.6:
|
||||
tee = subprocess.Popen(["tee", current_outfile],
|
||||
stdin=subprocess.PIPE)
|
||||
os.dup2(tee.stdin.fileno(), sys.stdout.fileno())
|
||||
os.dup2(tee.stdin.fileno(), sys.stderr.fileno())
|
||||
t = tempfile.NamedTemporaryFile(
|
||||
mode="w+b", suffix=".py", prefix=prefix
|
||||
)
|
||||
current_outfile = t.name
|
||||
sys.stdout = os.fdopen(sys.stdout.fileno(), "w", buffering)
|
||||
tee = subprocess.Popen(["tee", current_outfile], stdin=subprocess.PIPE)
|
||||
os.dup2(tee.stdin.fileno(), sys.stdout.fileno())
|
||||
os.dup2(tee.stdin.fileno(), sys.stderr.fileno())
|
||||
else:
|
||||
if filename.endswith(".pyc"):
|
||||
current_outfile = os.path.join(out_base, filename[0:-1])
|
||||
@@ -346,9 +345,9 @@ def main(
|
||||
pass
|
||||
pass
|
||||
tot_files += 1
|
||||
except (ValueError, SyntaxError, ParserError, pysource.SourceWalkerError):
|
||||
except (ValueError, SyntaxError, ParserError, pysource.SourceWalkerError) as e:
|
||||
sys.stdout.write("\n")
|
||||
sys.stderr.write("# file %s\n" % (infile))
|
||||
sys.stderr.write("\n# file %s\n# %s\n" % (infile, e))
|
||||
failed_files += 1
|
||||
tot_files += 1
|
||||
except KeyboardInterrupt:
|
||||
@@ -358,7 +357,7 @@ def main(
|
||||
sys.stdout.write("\n")
|
||||
sys.stderr.write("\nLast file: %s " % (infile))
|
||||
raise
|
||||
except RuntimeError, e:
|
||||
except RuntimeError as e:
|
||||
sys.stdout.write("\n%s\n" % str(e))
|
||||
if str(e).startswith("Unsupported Python"):
|
||||
sys.stdout.write("\n")
|
||||
@@ -401,16 +400,13 @@ def main(
|
||||
else:
|
||||
okay_files += 1
|
||||
pass
|
||||
except verify.VerifyCmpError, e:
|
||||
except verify.VerifyCmpError as e:
|
||||
print(e)
|
||||
verify_failed_files += 1
|
||||
os.rename(current_outfile, current_outfile + "_unverified")
|
||||
sys.stderr.write("### Error Verifying %s\n" % filename)
|
||||
sys.stderr.write(str(e) + "\n")
|
||||
if not outfile:
|
||||
sys.stderr.write("### Error Verifiying %s" %
|
||||
filename)
|
||||
sys.stderr.write(e)
|
||||
if raise_on_error:
|
||||
raise
|
||||
pass
|
||||
@@ -420,15 +416,16 @@ def main(
|
||||
okay_files += 1
|
||||
pass
|
||||
elif do_verify:
|
||||
sys.stderr.write("\n### uncompile successful, "
|
||||
"but no file to compare against")
|
||||
sys.stderr.write(
|
||||
"\n### uncompile successful, but no file to compare against\n"
|
||||
)
|
||||
pass
|
||||
else:
|
||||
okay_files += 1
|
||||
if not current_outfile:
|
||||
mess = "\n# okay decompiling"
|
||||
# mem_usage = __memUsage()
|
||||
print mess, infile
|
||||
print(mess, infile)
|
||||
if current_outfile:
|
||||
sys.stdout.write(
|
||||
"%s -- %s\r"
|
||||
|
@@ -19,16 +19,18 @@
|
||||
Common uncompyle6 parser routines.
|
||||
"""
|
||||
|
||||
from __future__ import print_function
|
||||
|
||||
import sys
|
||||
|
||||
from xdis.code import iscode
|
||||
from xdis import iscode
|
||||
from xdis.magics import py_str2float
|
||||
from spark_parser import GenericASTBuilder, DEFAULT_DEBUG as PARSER_DEFAULT_DEBUG
|
||||
from uncompyle6.show import maybe_show_asm
|
||||
|
||||
|
||||
class ParserError(Exception):
|
||||
def __init__(self, token, offset, debug):
|
||||
def __init__(self, token, offset, debug=PARSER_DEFAULT_DEBUG):
|
||||
self.token = token
|
||||
self.offset = offset
|
||||
self.debug = debug
|
||||
@@ -888,4 +890,5 @@ if __name__ == "__main__":
|
||||
ast = python_parser(PYTHON_VERSION, co, showasm=True, is_pypy=IS_PYPY)
|
||||
print(ast)
|
||||
return
|
||||
parse_test(parse_test.func_code)
|
||||
|
||||
parse_test(parse_test.__code__)
|
||||
|
@@ -25,6 +25,8 @@ If we succeed in creating a parse tree, then we have a Python program
|
||||
that a later phase can turn into a sequence of ASCII text.
|
||||
"""
|
||||
|
||||
from __future__ import print_function
|
||||
|
||||
from uncompyle6.parsers.reducecheck import (except_handler_else, ifelsestmt, tryelsestmt)
|
||||
from uncompyle6.parser import PythonParser, PythonParserSingle, nop_func
|
||||
from uncompyle6.parsers.treenode import SyntaxTree
|
||||
@@ -194,8 +196,9 @@ class Python2Parser(PythonParser):
|
||||
expr ::= slice3
|
||||
expr ::= unary_convert
|
||||
|
||||
and ::= expr jmp_false expr come_from_opt
|
||||
or ::= expr jmp_true expr come_from_opt
|
||||
expr_jt ::= expr jmp_true
|
||||
or ::= expr_jt expr come_from_opt
|
||||
and ::= expr jmp_false expr come_from_opt
|
||||
|
||||
unary_convert ::= expr UNARY_CONVERT
|
||||
|
||||
|
@@ -42,8 +42,6 @@ class Python24Parser(Python25Parser):
|
||||
POP_TOP POP_BLOCK COME_FROM
|
||||
while1stmt ::= SETUP_LOOP l_stmts_opt JUMP_BACK
|
||||
POP_TOP POP_BLOCK
|
||||
while1stmt ::= SETUP_LOOP l_stmts COME_FROM JUMP_BACK
|
||||
POP_TOP POP_BLOCK COME_FROM
|
||||
|
||||
continue ::= JUMP_BACK JUMP_ABSOLUTE
|
||||
|
||||
@@ -53,6 +51,11 @@ class Python24Parser(Python25Parser):
|
||||
while1stmt ::= SETUP_LOOP l_stmts
|
||||
POP_TOP POP_BLOCK
|
||||
|
||||
# The following has a "COME_FROM" at the end which comes from
|
||||
# a "break" inside "l_stmts".
|
||||
while1stmt ::= SETUP_LOOP l_stmts COME_FROM JUMP_BACK
|
||||
POP_TOP POP_BLOCK COME_FROM
|
||||
|
||||
# Python 2.5+:
|
||||
# call_stmt ::= expr POP_TOP
|
||||
# expr ::= yield
|
||||
@@ -106,6 +109,15 @@ class Python24Parser(Python25Parser):
|
||||
l = len(tokens)
|
||||
if 0 <= l < len(tokens):
|
||||
return not int(tokens[first].pattr) == tokens[last].offset
|
||||
elif lhs == 'try_except':
|
||||
if last == len(tokens):
|
||||
last -= 1
|
||||
if tokens[last] != 'COME_FROM' and tokens[last-1] == 'COME_FROM':
|
||||
last -= 1
|
||||
return (tokens[last] == 'COME_FROM'
|
||||
and tokens[last-1] == 'END_FINALLY'
|
||||
and tokens[last-2] == 'POP_TOP'
|
||||
and tokens[last-3].kind != 'JUMP_FORWARD')
|
||||
|
||||
return False
|
||||
|
||||
|
@@ -20,9 +20,6 @@ class Python25Parser(Python26Parser):
|
||||
|
||||
return_if_stmt ::= ret_expr RETURN_END_IF JUMP_BACK
|
||||
|
||||
# We have no jumps to jumps, so no "come_froms" but a single "COME_FROM"
|
||||
ifelsestmt ::= testexpr c_stmts_opt jf_cf_pop else_suite COME_FROM
|
||||
|
||||
# Python 2.6 uses ROT_TWO instead of the STORE_xxx
|
||||
# withas is allowed as a "from future" in 2.5
|
||||
# 2.6 and 2.7 do something slightly different
|
||||
@@ -46,8 +43,6 @@ class Python25Parser(Python26Parser):
|
||||
# loop. FIXME: should "come_froms" below be a single COME_FROM?
|
||||
tryelsestmt ::= SETUP_EXCEPT suite_stmts_opt POP_BLOCK
|
||||
except_handler else_suite come_froms
|
||||
tryelsestmtl ::= SETUP_EXCEPT suite_stmts_opt POP_BLOCK
|
||||
except_handler else_suitel
|
||||
|
||||
# Python 2.6 omits the LOAD_FAST DELETE_FAST below
|
||||
# withas is allowed as a "from future" in 2.5
|
||||
@@ -66,9 +61,6 @@ class Python25Parser(Python26Parser):
|
||||
def customize_grammar_rules(self, tokens, customize):
|
||||
# Remove grammar rules inherited from Python 2.6 or Python 2
|
||||
self.remove_rules("""
|
||||
# No jump to jumps in 2.4 so we have a single "COME_FROM", not "come_froms"
|
||||
ifelsestmt ::= testexpr c_stmts_opt jf_cf_pop else_suite come_froms
|
||||
|
||||
setupwith ::= DUP_TOP LOAD_ATTR ROT_TWO LOAD_ATTR CALL_FUNCTION_0 POP_TOP
|
||||
with ::= expr setupwith SETUP_FINALLY suite_stmts_opt
|
||||
POP_BLOCK LOAD_CONST COME_FROM WITH_CLEANUP END_FINALLY
|
||||
|
@@ -7,6 +7,7 @@ from xdis import next_offset
|
||||
from uncompyle6.parser import PythonParserSingle, nop_func
|
||||
from uncompyle6.parsers.parse2 import Python2Parser
|
||||
from uncompyle6.parsers.reducecheck import (
|
||||
or_check,
|
||||
ifelsestmt,
|
||||
tryelsestmt,
|
||||
)
|
||||
@@ -101,8 +102,9 @@ class Python27Parser(Python2Parser):
|
||||
ret_or ::= expr JUMP_IF_TRUE_OR_POP ret_expr_or_cond COME_FROM
|
||||
if_exp_ret ::= expr POP_JUMP_IF_FALSE expr RETURN_END_IF COME_FROM ret_expr_or_cond
|
||||
|
||||
or ::= expr JUMP_IF_TRUE_OR_POP expr COME_FROM
|
||||
and ::= expr JUMP_IF_FALSE_OR_POP expr COME_FROM
|
||||
expr_jitop ::= expr JUMP_IF_TRUE_OR_POP
|
||||
or ::= expr_jitop expr COME_FROM
|
||||
and ::= expr JUMP_IF_FALSE_OR_POP expr COME_FROM
|
||||
|
||||
# compare_chained{1,2} is used exclusively in chained_compare
|
||||
compare_chained1 ::= expr DUP_TOP ROT_THREE COMPARE_OP JUMP_IF_FALSE_OR_POP
|
||||
@@ -229,6 +231,7 @@ class Python27Parser(Python2Parser):
|
||||
# FIXME: Put more in this table
|
||||
self.reduce_check_table = {
|
||||
# "ifelsestmt": ifelsestmt,
|
||||
"or": or_check,
|
||||
"tryelsestmt": tryelsestmt,
|
||||
"tryelsestmtl": tryelsestmt,
|
||||
}
|
||||
@@ -239,7 +242,7 @@ class Python27Parser(Python2Parser):
|
||||
self.check_reduce["except_handler"] = "tokens"
|
||||
self.check_reduce["except_handler_else"] = "tokens"
|
||||
|
||||
# self.check_reduce["or"] = "AST"
|
||||
self.check_reduce["or"] = "AST"
|
||||
self.check_reduce["raise_stmt1"] = "AST"
|
||||
self.check_reduce["iflaststmtl"] = "AST"
|
||||
self.check_reduce["ifelsestmt"] = "AST"
|
||||
@@ -372,5 +375,4 @@ if __name__ == "__main__":
|
||||
for t in remain_tokens])
|
||||
remain_tokens = set(remain_tokens) - opcode_set
|
||||
print(remain_tokens)
|
||||
p.check_grammar()
|
||||
p.dump_grammar()
|
||||
# p.dump_grammar()
|
||||
|
@@ -74,6 +74,7 @@ class Python3Parser(PythonParser):
|
||||
|
||||
jb_or_c ::= JUMP_BACK
|
||||
jb_or_c ::= CONTINUE
|
||||
jb_cfs ::= JUMP_BACK _come_froms
|
||||
|
||||
stmt ::= set_comp_func
|
||||
|
||||
@@ -277,10 +278,16 @@ class Python3Parser(PythonParser):
|
||||
POP_BLOCK LOAD_CONST COME_FROM_WITH
|
||||
WITH_CLEANUP END_FINALLY
|
||||
|
||||
expr_jt ::= expr jmp_true
|
||||
expr_jitop ::= expr JUMP_IF_TRUE_OR_POP
|
||||
|
||||
## FIXME: Right now we have erroneous jump targets
|
||||
## This below is probably not correct when the COME_FROM is put in the right place
|
||||
and ::= expr jmp_false expr COME_FROM
|
||||
or ::= expr jmp_true expr COME_FROM
|
||||
and ::= expr jmp_false expr COME_FROM
|
||||
or ::= expr_jt expr COME_FROM
|
||||
or ::= expr_jt expr
|
||||
or ::= expr_jitop expr COME_FROM
|
||||
and ::= expr JUMP_IF_FALSE_OR_POP expr COME_FROM
|
||||
|
||||
# # something like the below is needed when the jump targets are fixed
|
||||
## or ::= expr JUMP_IF_TRUE_OR_POP COME_FROM expr
|
||||
@@ -338,9 +345,6 @@ class Python3Parser(PythonParser):
|
||||
ret_or ::= expr JUMP_IF_TRUE_OR_POP ret_expr_or_cond COME_FROM
|
||||
if_exp_ret ::= expr POP_JUMP_IF_FALSE expr RETURN_END_IF COME_FROM ret_expr_or_cond
|
||||
|
||||
or ::= expr JUMP_IF_TRUE_OR_POP expr COME_FROM
|
||||
or ::= expr jmp_true expr
|
||||
and ::= expr JUMP_IF_FALSE_OR_POP expr COME_FROM
|
||||
|
||||
# compare_chained1 is used exclusively in chained_compare
|
||||
compare_chained1 ::= expr DUP_TOP ROT_THREE COMPARE_OP JUMP_IF_FALSE_OR_POP
|
||||
@@ -435,10 +439,11 @@ class Python3Parser(PythonParser):
|
||||
while1elsestmt ::= SETUP_LOOP l_stmts JUMP_BACK
|
||||
else_suitel
|
||||
|
||||
whileelsestmt ::= SETUP_LOOP testexpr l_stmts_opt JUMP_BACK POP_BLOCK
|
||||
whileelsestmt ::= SETUP_LOOP testexpr l_stmts_opt jb_cfs POP_BLOCK
|
||||
else_suitel COME_FROM_LOOP
|
||||
|
||||
whileelsestmt2 ::= SETUP_LOOP testexpr l_stmts_opt JUMP_BACK POP_BLOCK
|
||||
|
||||
whileelsestmt2 ::= SETUP_LOOP testexpr l_stmts_opt JUMP_BACK POP_BLOCK
|
||||
else_suitel JUMP_BACK COME_FROM_LOOP
|
||||
|
||||
whileTruestmt ::= SETUP_LOOP l_stmts_opt JUMP_BACK POP_BLOCK
|
||||
@@ -505,8 +510,7 @@ class Python3Parser(PythonParser):
|
||||
"""
|
||||
# FIXME: I bet this can be simplified
|
||||
# look for next MAKE_FUNCTION
|
||||
j = i
|
||||
for i in range(j + 1, len(tokens)):
|
||||
for i in range(i + 1, len(tokens)):
|
||||
if tokens[i].kind.startswith("MAKE_FUNCTION"):
|
||||
break
|
||||
elif tokens[i].kind.startswith("MAKE_CLOSURE"):
|
||||
@@ -518,7 +522,6 @@ class Python3Parser(PythonParser):
|
||||
assert (
|
||||
tokens[i + 1].kind == "LOAD_STR"
|
||||
), "build_class expecting CONST after MAKE_FUNCTION/MAKE_CLOSURE"
|
||||
|
||||
call_fn_tok = None
|
||||
for i in range(i, len(tokens)):
|
||||
if tokens[i].kind.startswith("CALL_FUNCTION"):
|
||||
|
@@ -2,6 +2,7 @@
|
||||
"""
|
||||
spark grammar differences over Python 3.1 for Python 3.0.
|
||||
"""
|
||||
from __future__ import print_function
|
||||
|
||||
from uncompyle6.parser import PythonParserSingle
|
||||
from uncompyle6.parsers.parse31 import Python31Parser
|
||||
@@ -133,8 +134,9 @@ class Python30Parser(Python31Parser):
|
||||
|
||||
jump_except ::= _jump COME_FROM POP_TOP
|
||||
|
||||
expr_jt ::= expr jmp_true
|
||||
or ::= expr jmp_false expr jmp_true expr
|
||||
or ::= expr jmp_true expr
|
||||
or ::= expr_jt expr
|
||||
|
||||
import_from ::= LOAD_CONST LOAD_CONST IMPORT_NAME importlist _come_froms POP_TOP
|
||||
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user