Compare commits

...

39 Commits

Author SHA1 Message Date
rocky
e4cc126b38 Get ready for release 2.8.2 2016-08-29 21:48:21 -04:00
rocky
da458bdce7 Correct PYPY bit logic in previous commit 2016-08-27 20:19:12 -04:00
rocky
f47aecae9f PYPY bugs and inspired changes ...
verify.py: Show co_flags when different.
pysource.py: PYPY also generates normal tryfinallystmt code
test_pyenvlib.py: allow pypy-5.3.1
2016-08-27 19:32:42 -04:00
rocky
ddc5460030 Start to handle Python 3.1 bytecode 2016-08-26 20:50:08 -04:00
rocky
835c4151c3 Bump min requirement versions
xdis we need increased so we don't catch old xdis bugs
2016-08-26 08:02:27 -04:00
rocky
1087613a27 Handle 3.6 Format String conversions !r, !s, !a 2016-08-25 07:26:01 -04:00
rocky
a67891c563 Get ready for release 2.8.1 2016-08-20 22:14:36 -04:00
rocky
31413be7a1 Python 2.2 doesn't have opcode LIST_APPEND 2016-08-16 12:45:43 -04:00
rocky
98a6f47ad6 Python 2.2 scanner bug: don't mung IMPORT_NAME op 2016-08-16 06:38:09 -04:00
rocky
2e3e6658ee Small pypy LOOKUP_METHOD cleanups 2016-08-16 06:09:10 -04:00
R. Bernstein
85c562cb36 Merge pull request #49 from moagstar/master
Fixed a bug with FORMAT_VALUE with sub expressions.
2016-08-16 05:33:09 -04:00
moagstar
5ab3e52c9c disable test_format_specifiers on python < 3.6 since this is only required for the fstring tests and was causing failures on 2.7 2016-08-16 08:38:38 +02:00
DanielBradburn
004ce5c491 Fixed bug with FORMAT_VALUE where a sub expression would not be correctly interpreted 2016-08-16 08:24:06 +02:00
rocky
599ceddd08 xdis 2.1.1 removes some bugs encountered here 2016-08-14 23:11:55 -04:00
rocky
6547d0230f Merge branch 'master' of github.com:rocky/python-uncompyle6 2016-08-14 23:00:16 -04:00
rocky
a65443ee02 Fix pypy semantic action bug in CALL_METHOD 2016-08-14 22:59:34 -04:00
DanielBradburn
2bd850f297 added examples for known failures 2016-08-14 20:44:23 +02:00
R. Bernstein
90477edf04 Merge pull request #45 from rocky/revert-43-patch-1
Revert "Cache pip installation in travis"
2016-08-14 07:54:46 -04:00
R. Bernstein
c912d16b50 Merge pull request #46 from rocky/revert-44-patch-2
Revert "Test with latest PyPy in Travis"
2016-08-14 07:53:59 -04:00
R. Bernstein
8dd405a5ee Revert "Test with latest PyPy in Travis" 2016-08-14 07:53:47 -04:00
R. Bernstein
116a22a425 Merge pull request #44 from thedrow/patch-2
Test with latest PyPy in Travis
2016-08-14 07:53:40 -04:00
R. Bernstein
7d771b9a8c Revert "Cache pip installation in travis" 2016-08-14 07:46:55 -04:00
R. Bernstein
a1972bbc08 Merge pull request #43 from thedrow/patch-1
Cache pip installation in travis
2016-08-14 07:41:46 -04:00
Omer Katz
8a91081535 Fix indentation. 2016-08-14 11:03:49 +03:00
rocky
0958dc889d Back off of 3.6 testing for now 2016-08-13 23:33:23 -04:00
rocky
33a0c75b69 Merge branch 'master' of github.com:rocky/python-uncompyle6 2016-08-13 20:26:52 -04:00
rocky
7ccbd419c6 Correct SET_LINENO handling in Python 2.2
Add more  2.2 tests
2016-08-13 20:25:19 -04:00
rocky
a45ee15cf2 I said - we test 2.2 now. 2016-08-13 09:14:33 -04:00
rocky
fb5ad76c4e Include Python 2.2 in testing 2016-08-13 09:07:15 -04:00
rocky
d8598f61e4 Start handling Python 2.2 bytecode and...
Fix some bugs in Python 2.3-2.5 bytecode handling
2016-08-13 07:16:50 -04:00
Omer Katz
5f52cce24d Test with latest PyPy. 2016-08-11 11:15:33 +03:00
Omer Katz
70463e036a Cache pip installation 2016-08-11 11:13:58 +03:00
DanielBradburn
7fba24198f small formatting change 2016-08-10 22:29:02 +02:00
DanielBradburn
e06a90ed27 added hypothesis to requirements-dev 2016-08-10 22:27:54 +02:00
DanielBradburn
d030a04c1a added hypothesis test (currently failing due to limited support) for testing fstring uncompyling 2016-08-10 22:20:43 +02:00
Daniel Bradburn
37d5a05241 Merge pull request #2 from rocky/master
Merging pypy and cpython 3.6 from rocky
2016-08-10 08:22:15 +02:00
DanielBradburn
5d27832d6f resolve merge conflicts from pull request 2016-08-10 08:20:51 +02:00
Daniel Bradburn
d14865c1be Starting adding python 3.6 support to uncompyle 2016-07-28 09:07:12 +02:00
Daniel Bradburn
1be53ca729 Merge pull request #1 from rocky/master
Syncing with rocky
2016-07-24 16:56:36 +02:00
45 changed files with 565 additions and 52 deletions

186
ChangeLog
View File

@@ -1,6 +1,176 @@
2016-08-27 rocky <rb@dustyfeet.com>
* test/test_pyenvlib.py, uncompyle6/verify.py: Correct PYPY bit
logic in previous commit
2016-08-27 rocky <rb@dustyfeet.com>
* test/test_pyenvlib.py, uncompyle6/semantics/pysource.py,
uncompyle6/verify.py: PYPY bugs and inspired changes ... verify.py: Show co_flags when different. pysource.py: PYPY also
generates normal tryfinallystmt code test_pyenvlib.py: allow
pypy-5.3.1
2016-08-26 rocky <rb@dustyfeet.com>
* Makefile, test/Makefile, uncompyle6/parser.py,
uncompyle6/parsers/parse3.py, uncompyle6/scanner.py,
uncompyle6/scanners/scanner3.py: Start to handle Python 3.1 bytecode
2016-08-26 rocky <rb@dustyfeet.com>
* __pkginfo__.py, requirements.txt: Bump min requirement versions xdis we need increased so we don't catch old xdis bugs
2016-08-25 rocky <rb@dustyfeet.com>
* test/simple_source/bug36/01_fstring.py,
uncompyle6/semantics/pysource.py: Handle 3.6 Format String
conversions !r, !s, !a
2016-08-20 rocky <rb@dustyfeet.com>
* ChangeLog, NEWS, uncompyle6/version.py: Get ready for release
2.8.1
2016-08-16 rocky <rb@dustyfeet.com>
* test/simple_source/bug22/05_test_yield.py,
uncompyle6/scanners/scanner2.py: Python 2.2 doesn't have opcode
LIST_APPEND
2016-08-16 rocky <rb@dustyfeet.com>
* uncompyle6/scanners/scanner26.py: Python 2.2 scanner bug: don't
mung IMPORT_NAME op
2016-08-16 rocky <rb@dustyfeet.com>
* test/simple_source/bug_pypy27/02_call_method.py,
uncompyle6/parsers/parse2.py, uncompyle6/parsers/parse3.py: Small
pypy LOOKUP_METHOD cleanups
2016-08-16 R. Bernstein <rocky@users.noreply.github.com>
* : Merge pull request #49 from moagstar/master Fixed a bug with FORMAT_VALUE with sub expressions.
2016-08-16 DanielBradburn <moagstar@gmail.com>
* pytest/test_fstring.py, uncompyle6/parsers/parse3.py: Fixed bug
with FORMAT_VALUE where a sub expression would not be correctly
interpreted
2016-08-14 rocky <rb@dustyfeet.com>
* __pkginfo__.py: xdis 2.1.1 removes some bugs encountered here
2016-08-14 rocky <rb@dustyfeet.com>
* : commit a65443ee0225933367be9c7640629298882532c9 Author: rocky
<rb@dustyfeet.com> Date: Sun Aug 14 22:59:34 2016 -0400
2016-08-14 DanielBradburn <moagstar@gmail.com>
* pytest/test_fstring.py: added examples for known failures
2016-08-14 R. Bernstein <rocky@users.noreply.github.com>
* : Merge pull request #45 from rocky/revert-43-patch-1 Revert "Cache pip installation in travis"
2016-08-14 R. Bernstein <rocky@users.noreply.github.com>
* .travis.yml: Revert "Test with latest PyPy in Travis"
2016-08-14 R. Bernstein <rocky@users.noreply.github.com>
* : Merge pull request #44 from thedrow/patch-2 Test with latest PyPy in Travis
2016-08-14 R. Bernstein <rocky@users.noreply.github.com>
* : Merge pull request #43 from thedrow/patch-1 Cache pip installation in travis
2016-08-13 rocky <rb@dustyfeet.com>
* test/Makefile: Back off of 3.6 testing for now
2016-08-13 rocky <rb@dustyfeet.com>
* : commit 7ccbd419c6b26e8ae9d0929f1bfddedebce6bbaf Author: rocky
<rb@dustyfeet.com> Date: Sat Aug 13 20:25:19 2016 -0400
2016-08-13 rocky <rb@dustyfeet.com>
* test/Makefile: I said - we test 2.2 now.
2016-08-13 rocky <rb@dustyfeet.com>
* test/Makefile, test/simple_source/stmts/00_import.py,
test/test_pythonlib.py: Include Python 2.2 in testing
2016-08-13 rocky <rb@dustyfeet.com>
* README.rst, uncompyle6/parser.py, uncompyle6/parsers/parse22.py,
uncompyle6/scanner.py, uncompyle6/scanners/scanner22.py,
uncompyle6/scanners/scanner23.py, uncompyle6/scanners/scanner24.py,
uncompyle6/scanners/scanner25.py, uncompyle6/semantics/pysource.py:
Start handling Python 2.2 bytecode and... Fix some bugs in Python 2.3-2.5 bytecode handling
2016-08-11 Omer Katz <omer.drow@gmail.com>
* .travis.yml: Test with latest PyPy.
2016-08-11 Omer Katz <omer.drow@gmail.com>
* .travis.yml: Cache pip installation
2016-08-10 DanielBradburn <moagstar@gmail.com>
* pytest/test_fstring.py: small formatting change
2016-08-10 DanielBradburn <moagstar@gmail.com>
* pytest/test_fstring.py, requirements-dev.txt: added hypothesis to
requirements-dev
2016-08-10 DanielBradburn <moagstar@gmail.com>
* pytest/test_fstring.py: added hypothesis test (currently failing
due to limited support) for testing fstring uncompyling
2016-08-10 Daniel Bradburn <moagstar@gmail.com>
* : Merge pull request #2 from rocky/master Merging pypy and cpython 3.6 from rocky
2016-08-03 rocky <rb@dustyfeet.com>
* uncompyle6/version.py: Get ready for release 2.8.0
* : commit 109e813058380630bda82014eee94a9089cc4666 Author: rocky
<rb@dustyfeet.com> Date: Wed Aug 3 08:07:47 2016 -0400
2016-08-01 rocky <rb@dustyfeet.com>
* __pkginfo__.py, requirements.txt: Need recent xdis fix for 3.6
wordcode
2016-08-01 rocky <rb@dustyfeet.com>
* test/simple_source/bug36/01_fstring.py: Add Python 3.6
formatted_str test
2016-08-01 R. Bernstein <rocky@users.noreply.github.com>
* : Merge pull request #41 from rocky/3.6 Move forward on moagstar's Python 3.6 support
2016-08-01 rocky <rb@dustyfeet.com>
* Makefile, README.rst, test/Makefile, test/test_pythonlib.py,
uncompyle6/bin/uncompile.py, uncompyle6/parsers/parse3.py,
uncompyle6/parsers/parse36.py, uncompyle6/scanner.py,
uncompyle6/scanners/scanner36.py, uncompyle6/semantics/aligner.py,
uncompyle6/semantics/pysource.py, uncompyle6/verify.py: Moagstar's
3.6 wordcode + formattedValue rules
2016-07-30 rocky <rb@dustyfeet.com>
* uncompyle6/semantics/aligner.py: WIP try to keep line numbers the
same
2016-07-29 rocky <rb@dustyfeet.com>
@@ -12,6 +182,16 @@
uncompyle6/scanners/scanner3.py, uncompyle6/semantics/pysource.py:
Fix 3.5 misclassifying RETURN_VALUE We use location of SETUP_EXCEPT instructions to disambiguate.
2016-07-28 Daniel Bradburn <moagstar@gmail.com>
* README.rst, test/Makefile, test/bytecode_3.6/fstring.py,
test/bytecode_3.6/fstring_single.py, test/test_pythonlib.py,
uncompyle6/bin/uncompile.py, uncompyle6/parser.py,
uncompyle6/parsers/parse3.py, uncompyle6/scanner.py,
uncompyle6/scanners/scanner36.py, uncompyle6/semantics/pysource.py,
uncompyle6/verify.py: Starting adding python 3.6 support to
uncompyle
2016-07-28 rocky <rb@dustyfeet.com>
* uncompyle6/parsers/parse2.py, uncompyle6/parsers/parse23.py,
@@ -213,9 +393,9 @@
uncompyle6/scanners/scanner3.py, uncompyle6/semantics/pysource.py:
PyPy support * Use proper PYPY 32 opcodes * handle opcodes LOOKUP_METHOD and CALL_METHOD * Administrative stuff for PyPy
2016-07-24 rocky <rb@dustyfeet.com>
2016-07-24 Daniel Bradburn <moagstar@gmail.com>
* test/add-test.py: add-test: Make sure PyPy bytecode is separated
* : Merge pull request #1 from rocky/master Syncing with rocky
2016-07-24 rocky <rb@dustyfeet.com>

View File

@@ -33,7 +33,7 @@ check-2.7 check-3.3 check-3.4: pytest
#: Tests for Python 3.2 and 3.5 - pytest doesn't work here
# Or rather 3.5 doesn't work not on Travis
check-3.2 check-3.5 check-3.6:
check-3.1 check-3.2 check-3.5 check-3.6:
$(MAKE) -C test $@
#:Tests for Python 2.6 (doesn't have pytest)

8
NEWS
View File

@@ -1,3 +1,11 @@
uncompyle6 2.8.1 2016-08-20
- Add Python 2.2 decompilation
- Fix bugs
* PyPy LOOKUP_METHOD bug
* Python 3.6 FORMAT_VALUE handles expressions now
uncompyle6 2.8.0 2016-08-03
- Start Python 3.6 support (moagstar)

View File

@@ -11,7 +11,7 @@ Introduction
------------
*uncompyle6* translates Python bytecode back into equivalent Python
source code. It accepts bytecodes from Python version 2.3 to 3.6 or
source code. It accepts bytecodes from Python version 2.2 to 3.6 or
so, including PyPy bytecode.
Why this?
@@ -45,7 +45,7 @@ Requirements
This project requires Python 2.6 or later, PyPy 3-2.4, or PyPy-5.0.1.
The bytecode files it can read has been tested on Python bytecodes from
versions 2.3-2.7, and 3.2-3.6 and the above-mentioned PyPy versions.
versions 2.2-2.7, and 3.2-3.6 and the above-mentioned PyPy versions.
Installation
------------

View File

@@ -23,6 +23,7 @@ classifiers = ['Development Status :: 4 - Beta',
'Programming Language :: Python :: 3.3',
'Programming Language :: Python :: 3.4',
'Programming Language :: Python :: 3.5',
'Programming Language :: Python :: 3.6',
'Topic :: Software Development :: Debuggers',
'Topic :: Software Development :: Libraries :: Python Modules',
]
@@ -37,7 +38,7 @@ entry_points={
]}
ftp_url = None
install_requires = ['spark-parser >= 1.4.0',
'xdis >= 2.1.0']
'xdis >= 2.2.3']
license = 'MIT'
mailing_list = 'python-debugger@googlegroups.com'
modname = 'uncompyle6'

136
pytest/test_fstring.py Normal file
View File

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

View File

@@ -1,2 +1,3 @@
pytest
flake8
hypothesis

View File

@@ -1,2 +1,2 @@
spark-parser >= 1.2.1
xdis >= 2.1.0
spark-parser >= 1.4.0
xdis >= 2.2.2

View File

@@ -22,6 +22,10 @@ check:
#: Run working tests from Python 2.6 or 2.7
check-2.6 check-2.7: check-bytecode-2 check-bytecode-3 check-2.7-ok
#: Run working tests from Python 3.1
check-3.2: check-bytecode
$(PYTHON) test_pythonlib.py --bytecode-3.1 --verify $(COMPILE)
#: Run working tests from Python 3.2
check-3.2: check-bytecode
$(PYTHON) test_pythonlib.py --bytecode-3.2 --verify $(COMPILE)
@@ -48,19 +52,25 @@ check-disasm:
#: Check deparsing bytecode 2.x only
check-bytecode-2:
$(PYTHON) test_pythonlib.py --bytecode-2.3 --bytecode-2.4 \
$(PYTHON) test_pythonlib.py \
--bytecode-2.2 --bytecode-2.3 --bytecode-2.4 \
--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.2 --bytecode-3.3 \
--bytecode-3.4 --bytecode-3.5 --bytecode-3.6 --bytecode-pypy3.2
--bytecode-3.4 --bytecode-3.5 --bytecode-pypy3.2
#: Check deparsing bytecode that works running Python 2 and Python 3
check-bytecode: check-bytecode-3
$(PYTHON) test_pythonlib.py --bytecode-2.3 --bytecode-2.4 \
$(PYTHON) test_pythonlib.py \
--bytecode-2.2 --bytecode-2.3 --bytecode-2.4 \
--bytecode-2.5 --bytecode-2.6 --bytecode-2.7 --bytecode-pypy2.7
#: Check deparsing Python 2.2
check-bytecode-2.3:
$(PYTHON) test_pythonlib.py --bytecode-2.2
#: Check deparsing Python 2.3
check-bytecode-2.3:
$(PYTHON) test_pythonlib.py --bytecode-2.3

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -0,0 +1,5 @@
def fn(var1, var2):
return f'interpolate {var1} strings {var2} py36'
fn('a', 'b')

View File

@@ -0,0 +1,2 @@
def fn(var):
return f'interpolate {var} strings'

Binary file not shown.

View File

@@ -0,0 +1,27 @@
# decompyle's test_appyEquiv.py
def kwfunc(**kwargs):
print kwargs.items()
def argsfunc(*args):
print args
def no_apply(*args, **kwargs):
print args
print kwargs.items()
argsfunc(34)
foo = argsfunc(*args)
argsfunc(*args)
argsfunc(34, *args)
kwfunc(**None)
kwfunc(x = 11, **None)
no_apply(*args, **args)
no_apply(34, *args, **args)
no_apply(x = 11, *args, **args)
no_apply(34, x = 11, *args, **args)
no_apply(42, 34, x = 11, *args, **args)
return foo
no_apply(1, 2, 4, 8, a = 2, b = 3, c = 5)

View File

@@ -0,0 +1,24 @@
# From decompyle
# In Python 2.2 we don't have op LIST_APPEND while in > 2.3 we do.
from __future__ import generators
def inorder(t):
if t:
for x in inorder(t.left):
yield x
yield t.label
for x in inorder(t.right):
yield x
def generate_ints(n):
for i in range(n):
yield i * 2
for i in generate_ints(5):
print i,
print
gen = generate_ints(3)
print gen.next(), gen.next(), gen.next(), gen.next()

View File

@@ -1,3 +1,3 @@
var1 = 'x'
var2 = 'y'
print(f'interpolate {var1} strings {var2} py36')
print(f'interpolate {var1} strings {var2!r} {var2!s} py36')

View File

@@ -0,0 +1,4 @@
# Bug in PyPy was not handling CALL_METHOD_xxx like
# CALL_FUNCTION_XXX
def truncate(self, size=None):
self.db.put(self.key, '', txn=self.txn, dlen=self.len - size, doff=size)

View File

@@ -3,3 +3,4 @@
import sys
from os import path
from os import *
import time as time1, os as os1

View File

@@ -27,9 +27,10 @@ from fnmatch import fnmatch
#----- configure this for your needs
TEST_VERSIONS=('2.3.7', '2.4.6', '2.5.6', '2.6.9', 'pypy-2.6.1',
'pypy-5.0.1',
'2.7.10', '2.7.11',
TEST_VERSIONS=('2.3.7', '2.4.6', '2.5.6', '2.6.9',
'pypy-2.4.0', 'pypy-2.6.1',
'pypy-5.0.1', 'pypy-5.3.1',
'2.7.10', '2.7.11', '2.7.12',
'3.2.6', '3.3.5', '3.4.2', '3.5.1')
target_base = '/tmp/py-dis/'

View File

@@ -78,7 +78,8 @@ for vers in (2.7, 3.4, 3.5, 3.6):
test_options[key] = (os.path.join(src_dir, pythonlib), PYOC, key, vers)
pass
for vers in (2.3, 2.4, 2.5, 2.6, 2.7, 3.2, 3.3, 3.4, 3.5, 3.6, 'pypy3.2', 'pypy2.7'):
for vers in (2.2, 2.3, 2.4, 2.5, 2.6, 2.7,
3.2, 3.3, 3.4, 3.5, 3.6, 'pypy3.2', 'pypy2.7'):
bytecode = "bytecode_%s" % vers
key = "bytecode-%s" % vers
test_options[key] = (bytecode, PYC, bytecode, vers)

View File

@@ -269,9 +269,6 @@ class PythonParser(GenericASTBuilder):
"""
_for ::= GET_ITER FOR_ITER
# Possibly before Python 2.3
# _for ::= LOAD_CONST FOR_LOOP
for_block ::= l_stmts_opt _come_from JUMP_BACK
for_block ::= return_stmts _come_from
@@ -546,7 +543,13 @@ def get_python_parser(
# FIXME: there has to be a better way...
if version < 3.0:
if version == 2.3:
if version == 2.2:
import uncompyle6.parsers.parse22 as parse22
if compile_mode == 'exec':
p = parse22.Python22Parser(debug_parser)
else:
p = parse22.Python22ParserSingle(debug_parser)
elif version == 2.3:
import uncompyle6.parsers.parse23 as parse23
if compile_mode == 'exec':
p = parse23.Python23Parser(debug_parser)
@@ -587,7 +590,12 @@ def get_python_parser(
pass
else:
import uncompyle6.parsers.parse3 as parse3
if version == 3.2:
if version == 3.1:
if compile_mode == 'exec':
p = parse3.Python31Parser(debug_parser)
else:
p = parse3.Python31ParserSingle(debug_parser)
elif version == 3.2:
if compile_mode == 'exec':
p = parse3.Python32Parser(debug_parser)
else:

View File

@@ -409,7 +409,7 @@ class Python2Parser(PythonParser):
+ 'expr ' * nak + opname
elif opname_base == 'CALL_METHOD':
# PyPy only - DRY with parse3
args_pos = (v & 0xff) # positional parameters
args_pos = (v & 0xff) # positional parameters
args_kw = (v >> 8) & 0xff # keyword parameters
# number of apply equiv arguments:
nak = ( len(opname_base)-len('CALL_METHOD') ) // 3

View File

@@ -0,0 +1,29 @@
# Copyright (c) 2016 Rocky Bernstein
# Copyright (c) 2000-2002 by hartmut Goebel <hartmut@goebel.noris.de>
from spark_parser import DEFAULT_DEBUG as PARSER_DEFAULT_DEBUG
from uncompyle6.parser import PythonParserSingle
from uncompyle6.parsers.parse23 import Python23Parser
class Python22Parser(Python23Parser):
def __init__(self, debug_parser=PARSER_DEFAULT_DEBUG):
super(Python23Parser, self).__init__(debug_parser)
self.customized = {}
def p_misc22(self, args):
'''
_for ::= LOAD_CONST FOR_LOOP
'''
class Python22ParserSingle(Python23Parser, PythonParserSingle):
pass
if __name__ == '__main__':
# Check grammar
p = Python22Parser()
p.checkGrammar()
p.dumpGrammar()
# local variables:
# tab-width: 4

View File

@@ -461,8 +461,8 @@ class Python3Parser(PythonParser):
elif opname == 'FORMAT_VALUE':
# Python 3.6+
self.addRule("""
formatted_value ::= LOAD_FAST FORMAT_VALUE
formatted_value ::= LOAD_NAME FORMAT_VALUE
formatted_value ::= expr FORMAT_VALUE
formatted_value ::= expr FORMAT_VALUE
str ::= LOAD_CONST
formatted_value_or_str ::= formatted_value
formatted_value_or_str ::= str
@@ -492,6 +492,7 @@ class Python3Parser(PythonParser):
rule = ('load_closure ::= %s%s' % (('LOAD_CLOSURE ' * v), opname))
self.add_unique_rule(rule, opname, token.attr, customize)
if opname_base == 'BUILD_LIST' and saw_format_value:
saw_format_value = False
format_or_str_n = "formatted_value_or_str_%s" % v
self.addRule("""
expr ::= joined_str
@@ -580,14 +581,17 @@ class Python3Parser(PythonParser):
self.add_unique_rule(rule, opname, token.attr, customize)
elif opname_base == 'CALL_METHOD':
# PyPy only - DRY with parse2
# FIXME: The below argument parsing will be wrong when PyPy gets to 3.6
args_pos = (token.attr & 0xff) # positional parameters
args_kw = (token.attr >> 8) & 0xff # keyword parameters
# number of apply equiv arguments:
nak = ( len(opname_base)-len('CALL_METHOD') ) // 3
rule = ('call_function ::= expr '
+ ('pos_arg ' * args_pos)
+ ('kwarg ' * args_kw)
+ 'expr ' * nak + token.type)
+ 'expr ' * nak + opname)
self.add_unique_rule(rule, opname, token.attr, customize)
elif opname.startswith('MAKE_CLOSURE'):
# DRY with MAKE_FUNCTION
@@ -631,6 +635,15 @@ class Python3Parser(PythonParser):
return
class Python31Parser(Python3Parser):
def p_31(self, args):
"""
# Store locals is only in Python 3.0 to 3.3
stmt ::= store_locals
store_locals ::= LOAD_FAST STORE_LOCALS
"""
class Python32Parser(Python3Parser):
def p_32(self, args):
@@ -656,6 +669,9 @@ class Python3ParserSingle(Python3Parser, PythonParserSingle):
pass
class Python31ParserSingle(Python31Parser, PythonParserSingle):
pass
class Python32ParserSingle(Python32Parser, PythonParserSingle):
pass

View File

@@ -22,7 +22,8 @@ from uncompyle6 import PYTHON3, IS_PYPY
from uncompyle6.scanners.tok import Token
# The byte code versions we support
PYTHON_VERSIONS = (2.3, 2.4, 2.5, 2.6, 2.7, 3.2, 3.3, 3.4, 3.5, 3.6)
PYTHON_VERSIONS = (2.2, 2.3, 2.4, 2.5, 2.6, 2.7,
3.1, 3.2, 3.3, 3.4, 3.5, 3.6)
# FIXME: DRY
if PYTHON3:

View File

@@ -381,7 +381,8 @@ class Scanner2(scan.Scanner):
j = self.prev[s]
while code[j] == self.opc.JUMP_ABSOLUTE:
j = self.prev[j]
if code[j] == self.opc.LIST_APPEND: # list comprehension
if (self.version >= 2.3 and
code[j] == self.opc.LIST_APPEND): # list comprehension
stmts.remove(s)
continue
elif code[s] == self.opc.POP_TOP and code[self.prev[s]] == self.opc.ROT_TWO:

View File

@@ -0,0 +1,35 @@
# Copyright (c) 2016 by Rocky Bernstein
"""
Python 2.2 bytecode scanner/deparser
This overlaps Python's 2.2's dis module, but it can be run from
Python 3 and other versions of Python. Also, we save token
information for later use in deparsing.
"""
import uncompyle6.scanners.scanner23 as scan
# from uncompyle6.scanners.scanner26 import disassemble as disassemble26
# bytecode verification, verify(), uses JUMP_OPs from here
from xdis.opcodes import opcode_22
JUMP_OPs = opcode_22.JUMP_OPs
# We base this off of 2.3 instead of the other way around
# because we cleaned things up this way.
# The history is that 2.7 support is the cleanest,
# then from that we got 2.6 and so on.
class Scanner22(scan.Scanner23):
def __init__(self, show_asm=False):
scan.Scanner23.__init__(self, show_asm)
self.opc = opcode_22
self.opname = opcode_22.opname
self.version = 2.2
self.genexpr_name = '<generator expression>';
self.parent_injest = self.disassemble
self.disassemble = self.disassemble22
return
def disassemble22(self, co, classname=None, code_objects={}, show_asm=None):
tokens, customize = self.parent_injest(co, classname, code_objects, show_asm)
tokens = [t for t in tokens if t.type != 'SET_LINENO']
return tokens, customize

View File

@@ -1,8 +1,8 @@
# Copyright (c) 2016 by Rocky Bernstein
"""
Python 2.4 bytecode scanner/deparser
Python 2.3 bytecode scanner/deparser
This overlaps Python's 2.4's dis module, but it can be run from
This overlaps Python's 2.3's dis module, but it can be run from
Python 3 and other versions of Python. Also, we save token
information for later use in deparsing.
"""
@@ -20,6 +20,8 @@ JUMP_OPs = opcode_23.JUMP_OPs
class Scanner23(scan.Scanner24):
def __init__(self, show_asm):
scan.Scanner24.__init__(self, show_asm)
self.opc = opcode_23
self.opname = opcode_23.opname
# These are the only differences in initialization between
# 2.3-2.6
self.version = 2.3

View File

@@ -22,6 +22,8 @@ class Scanner24(scan.Scanner25):
scan.Scanner25.__init__(self, show_asm)
# These are the only differences in initialization between
# 2.4, 2.5 and 2.6
self.opc = opcode_24
self.opname = opcode_24.opname
self.version = 2.4
self.genexpr_name = '<generator expression>';
return

View File

@@ -21,6 +21,8 @@ class Scanner25(scan.Scanner26):
def __init__(self, show_asm):
# There are no differences in initialization between
# 2.5 and 2.6
self.opc = opcode_25
self.opname = opcode_25.opname
scan.Scanner26.__init__(self, show_asm)
self.version = 2.5
return

View File

@@ -79,6 +79,7 @@ class Scanner26(scan.Scanner2):
'''
show_asm = self.show_asm if not show_asm else show_asm
# show_asm = 'both'
if show_asm in ('both', 'before'):
from xdis.bytecode import Bytecode
bytecode = Bytecode(co, self.opc)
@@ -160,7 +161,8 @@ class Scanner26(scan.Scanner2):
self.opc.IMPORT_STAR))
# Changes IMPORT_NAME to IMPORT_NAME_CONT.
# Possibly a Python 2.0 hangover
if len(imports) > 1 and self.version < 2.3:
# FIXME: Move into a < 2.2 scanner.
if len(imports) > 1 and self.version < 2.2:
last_import = imports[0]
for i in imports[1:]:
if self.lines[last_import].next > i:

View File

@@ -52,10 +52,9 @@ class Scanner3(Scanner):
# Note: super initilization above initializes self.opc
# Opcodes that can start a statement.
self.statement_opcodes = frozenset([
statement_opcodes = [
self.opc.SETUP_LOOP, self.opc.BREAK_LOOP, self.opc.CONTINUE_LOOP,
self.opc.SETUP_FINALLY, self.opc.END_FINALLY, self.opc.SETUP_EXCEPT,
self.opc.SETUP_WITH,
self.opc.POP_BLOCK, self.opc.STORE_FAST, self.opc.DELETE_FAST,
self.opc.STORE_DEREF,
@@ -67,7 +66,12 @@ class Scanner3(Scanner):
self.opc.RETURN_VALUE, self.opc.RAISE_VARARGS, self.opc.POP_TOP,
self.opc.PRINT_EXPR, self.opc.JUMP_ABSOLUTE
])
]
if version >= 3.2:
statement_opcodes.append(self.opc.SETUP_WITH)
self.statement_opcodes = frozenset(statement_opcodes)
# Opcodes that can start a designator non-terminal.
# FIXME: JUMP_ABSOLUTE is weird. What's up with that?

View File

@@ -312,12 +312,13 @@ TABLE_DIRECT = {
'forelselaststmtl': (
'%|for %c in %c:\n%+%c%-%|else:\n%+%c%-\n\n', 3, 1, 4, -2),
'trystmt': ( '%|try:\n%+%c%-%c\n\n', 1, 3 ),
'tryelsestmt': ( '%|try:\n%+%c%-%c%|else:\n%+%c%-\n\n', 1, 3, 4 ),
'tryelsestmtc': ( '%|try:\n%+%c%-%c%|else:\n%+%c%-', 1, 3, 4 ),
'tryelsestmtl': ( '%|try:\n%+%c%-%c%|else:\n%+%c%-', 1, 3, 4 ),
'tf_trystmt': ( '%c%-%c%+', 1, 3 ),
'tf_tryelsestmt': ( '%c%-%c%|else:\n%+%c', 1, 3, 4 ),
'except': ('%|except:\n%+%c%-', 3 ),
'tryelsestmt': ( '%|try:\n%+%c%-%c%|else:\n%+%c%-\n\n', 1, 3, 4 ),
'tryelsestmtc': ( '%|try:\n%+%c%-%c%|else:\n%+%c%-', 1, 3, 4 ),
'tryelsestmtl': ( '%|try:\n%+%c%-%c%|else:\n%+%c%-', 1, 3, 4 ),
'tf_trystmt': ( '%c%-%c%+', 1, 3 ),
'tf_tryelsestmt': ( '%c%-%c%|else:\n%+%c', 1, 3, 4 ),
'tryfinallystmt': ( '%|try:\n%+%c%-%|finally:\n%+%c%-\n\n', 1, 5 ),
'except': ( '%|except:\n%+%c%-', 3 ),
'except_cond1': ( '%|except %c:\n', 1 ),
'except_cond2': ( '%|except %c as %c:\n', 1, 5 ),
'except_suite': ( '%+%c%-%C', 0, (1, maxint, '') ),
@@ -329,7 +330,9 @@ TABLE_DIRECT = {
'kv': ( '%c: %c', 3, 1 ),
'kv2': ( '%c: %c', 1, 2 ),
'mapexpr': ( '{%[1]C}', (0, maxint, ', ') ),
'importstmt': ( '%|import %c\n', 2),
'importfrom': ( '%|from %[2]{pattr} import %c\n', 3 ),
'importstar': ( '%|from %[2]{pattr} import *\n', ),
}
@@ -531,7 +534,6 @@ class SourceWalker(GenericASTTraversal, object):
'assert': ( '%|assert %c\n' , 0 ),
'assert2': ( '%|assert %c, %c\n' , 0, 3 ),
'trystmt': ( '%|try:\n%+%c%-%c\n\n', 1, 3 ),
'tryfinallystmt': ( '%|try:\n%+%c%-%|finally:\n%+%c%-\n\n', 1, 5 ),
'assign2': ( '%|%c, %c = %c, %c\n', 3, 4, 0, 1 ),
'assign3': ( '%|%c, %c, %c = %c, %c, %c\n', 5, 6, 7, 0, 1, 2 ),
})
@@ -560,14 +562,12 @@ class SourceWalker(GenericASTTraversal, object):
'importfrom20': ( '%|from %[1]{pattr} import %c\n', 2 ),
'importlist20': ( '%C', (0, maxint, ', ') ),
})
elif version >= 2.5:
########################
# Import style for 2.5+
########################
TABLE_DIRECT.update({
'importstmt': ( '%|import %c\n', 2),
'importstar': ( '%|from %[2]{pattr} import *\n', ),
'importfrom': ( '%|from %[2]{pattr} import %c\n', 3 ),
'importmultiple': ( '%|import %c%c\n', 2, 3 ),
'import_cont' : ( ', %c', 2 ),
})
@@ -591,7 +591,8 @@ class SourceWalker(GenericASTTraversal, object):
# Python 3.6+ Additions
#######################
TABLE_DIRECT.update({
'formatted_value': ( '{%c}', 0),
'formatted_value': ( '{%c%c}', 0, 1),
'FORMAT_VALUE': ( '%{pattr}', ),
'joined_str': ( "f'%c'", 2),
})
return
@@ -1730,8 +1731,7 @@ class SourceWalker(GenericASTTraversal, object):
%c, %C, and so on.
"""
# self.println("-----")
# self.print(startnode)
# self.println("----> ", startnode.type)
fmt = entry[0]
arg = 1
@@ -1850,11 +1850,10 @@ class SourceWalker(GenericASTTraversal, object):
continue
op = k[ :k.rfind('_') ]
if k == 'CALL_METHOD':
if k.startswith('CALL_METHOD'):
# This happens in PyPy only
TABLE_R[k] = ('%c(%P)', 0, (1, -1, ', ', 100))
if op == 'CALL_FUNCTION':
elif op == 'CALL_FUNCTION':
TABLE_R[k] = ('%c(%P)', 0, (1, -1, ', ', 100))
elif op in ('CALL_FUNCTION_VAR',
'CALL_FUNCTION_VAR_KW', 'CALL_FUNCTION_KW'):

View File

@@ -16,6 +16,7 @@ from uncompyle6 import PYTHON3
from xdis.code import iscode
from xdis.magics import PYTHON_MAGIC_INT
from xdis.load import load_file, load_module
from xdis.util import pretty_flags
# FIXME: DRY
if PYTHON3:
@@ -335,6 +336,16 @@ def cmp_code_objects(version, is_pypy, code_obj1, code_obj2, name=''):
for c1, c2 in zip(codes1, codes2):
cmp_code_objects(version, is_pypy, c1, c2, name=name)
elif member == 'co_flags':
flags1 = code_obj1.co_flags
flags2 = code_obj2.co_flags
if is_pypy:
# For PYPY for now we don't care about PYPY_SOURCE_IS_UTF8:
flags2 &= ~0x0100 # PYPY_SOURCE_IS_UTF8
if flags1 != flags2:
raise CmpErrorMember(name, 'co_flags',
pretty_flags(flags1),
pretty_flags(flags2))
else:
# all other members must be equal
if getattr(code_obj1, member) != getattr(code_obj2, member):

View File

@@ -1,3 +1,3 @@
# This file is suitable for sourcing inside bash as
# well as importing into Python
VERSION='2.8.0'
VERSION='2.8.2'