Compare commits

..

20 Commits

Author SHA1 Message Date
rocky
0e5eb954b2 Adminstrivia 2019-04-19 06:01:06 -04:00
rocky
7d9286b353 Get ready for release 3.3.1 2019-04-19 05:51:05 -04:00
rocky
0de99e5d44 Scale back "try" vs. "tryelse" reduction test on 3.6+ 2019-04-18 16:45:44 -04:00
rocky
52af2ba32a 3.6+ lambda parameter handling 2019-04-18 14:21:52 -04:00
rocky
bd0db6c539 Extend annotate test to 3.7 2019-04-18 09:47:54 -04:00
rocky
8663b4ca52 Fix bugs caused by last commit 2019-04-18 07:31:16 -04:00
rocky
b2dd58a85e Hacky attemp to add more 3.x annotate information in 2019-04-18 02:26:50 -04:00
rocky
97cb193a71 3.7 chained comparison grammar 2019-04-17 23:41:41 -04:00
rocky
e6e60cb49d 3.6 Chained compare 2019-04-17 15:44:33 -04:00
rocky
2ea8c3b1b1 3.7 and 3.8 chained compare fixups 2019-04-16 10:19:16 -04:00
rocky
701d2af54e Improve Python 2.7 generator handling 2019-04-15 23:14:44 -04:00
rocky
8a4189bc0e Python 2.6-2.7ish generator handling 2019-04-15 20:32:15 -04:00
rocky
0c4ab699b5 3.4+ while handling with returns ...
these while loops don't have a JUMP_BACK in them
2019-04-15 12:03:11 -04:00
rocky
8e11c53064 More cleanup from recent refactoring 2019-04-15 08:18:31 -04:00
rocky
b4c66d4307 Was missing some 3.7 and 3.7 semantic actions...
Possibly some as a result of the last refactor?
2019-04-15 08:11:31 -04:00
rocky
53968e535f Split up version-specific semantic action code more 2019-04-14 21:47:16 -04:00
rocky
d2381fbe11 Update dates and version numbers 2019-04-14 19:54:53 -04:00
rocky
d413ebe0e1 Split out semantic actions per version ...
In version 3.5..3.8 there are quite hefty changes.
2019-04-14 19:25:56 -04:00
rocky
f96522e18e Add 3.8 try else 2019-04-14 19:01:33 -04:00
rocky
50d50af2ee Doc typo 2019-04-14 07:45:06 -04:00
158 changed files with 1831 additions and 1299 deletions

View File

@@ -42,7 +42,7 @@ jobs:
# This is based on your 1.0 configuration file or project settings
- run:
working_directory: ~/rocky/python-uncompyle6
command: pyenv install 2.4.6 && pyenv local 2.4.6 && pyenv rehash && easy_install nose && pyenv rehash
command: pyenv local 2.7.11 && pyenv rehash && pip install virtualenv && pip install nose && pip install pep8 && pip install six && pyenv rehash
# Dependencies
# This would typically go in either a build or a build-and-test job when using workflows
# Restore the dependency cache
@@ -55,7 +55,9 @@ jobs:
# Any branch if there are none on the default branch - this should be unnecessary if you have your default branch configured correctly
- v1-dep-
# This is based on your 1.0 configuration file or project settings
- run: easy_install spark_parser==1.8.5 && easy_install xdis==3.8.4
- run: pip install --upgrade setuptools
- run: pip install -e .
- run: pip install pytest==3.2.5 hypothesis==3.0.0
# Save dependency cache
- save_cache:
key: v1-dep-{{ .Branch }}-{{ epoch }}
@@ -73,8 +75,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: python ./setup.py develop && make check-2.4
- run: cd ./test/stdlib && pyenv local 2.4.6 && bash ./runtests.sh 'test_[p-z]*.py'
- run: python ./setup.py develop && make check-2.7
- run: cd ./test/stdlib && pyenv local 2.7.11 && 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

View File

@@ -1,11 +1,15 @@
language: python
python:
- '2.7' # this is a cheat here because travis doesn't do 2.4-2.6
- '3.5'
- '2.7'
- '2.6'
- '3.4'
- '3.6'
matrix:
include:
- python: '2.7'
- python: '3.7'
dist: xenial # required for Python >= 3.7 (travis-ci/travis-ci#9069)
install:

View File

@@ -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
View File

@@ -1,7 +1,22 @@
3.3.0 2019-03-23 Holy Week
3.3.1 2019-04-19 Good Friday
==========================
* First cut at Python 3.8 (many bug remain)
Lots of decomplation bugs, especially in the 3.x series fixed. Don't worry though, many more remain.
* Add annotation return values in 3.6+
* Fix 3.6+ lambda parameter handling decompilation
* Fix 3.7+ chained comparision decompilation
* split out semantic-action customization into more separate files
* Add 3.8 try/else
* Fix 2.7 generator decompilation
* Fix some parser failures fixes in 3.4+ using test_pyenvlib
* Add more run tests
3.3.0 2019-43-14 Holy Week
==========================
* First cut at Python 3.8 (many bugs remain)
* Reinstate -c | --compile (compile before disassembly) option
* The usual smattering of bug and doc fixes
3.2.6 2019-03-23 Mueller Report

View File

@@ -12,7 +12,7 @@ Introduction
*uncompyle6* translates Python bytecode back into equivalent Python
source code. It accepts bytecodes from Python version 1.3 to version
3.7, spanning over 22 years of Python releases. We include Dropbox's
3.8, spanning over 24 years of Python releases. We include Dropbox's
Python 2.5 bytecode and some PyPy bytecode.
Why this?
@@ -76,7 +76,7 @@ Requirements
The code here can be run on Python versions 2.6 or later, PyPy 3-2.4,
or PyPy-5.0.1. Python versions 2.4-2.7 are supported in the
python-2.4 branch. The bytecode files it can read have been tested on
Python bytecodes from versions 1.4, 2.1-2.7, and 3.0-3.6 and the
Python bytecodes from versions 1.4, 2.1-2.7, and 3.0-3.8 and the
above-mentioned PyPy versions.
Installation

View File

@@ -43,6 +43,7 @@ classifiers = ['Development Status :: 5 - Production/Stable',
'Programming Language :: Python :: 3.5',
'Programming Language :: Python :: 3.6',
'Programming Language :: Python :: 3.7',
'Programming Language :: Python :: 3.8',
'Topic :: Software Development :: Debuggers',
'Topic :: Software Development :: Libraries :: Python Modules',
]

0
admin-tools/check-newer-versions.sh Normal file → Executable file
View File

0
admin-tools/check-older-versions.sh Normal file → Executable file
View File

View File

@@ -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}*

View File

@@ -5,4 +5,4 @@ if [[ $0 == ${BASH_SOURCE[0]} ]] ; then
echo "This script should be *sourced* rather than run directly through bash"
exit 1
fi
export PYVERSIONS='3.2.6 3.6.8 3.7.2 2.6.9 3.3.7 2.7.15 3.2.6 3.1.5 3.4.8'
export PYVERSIONS='3.6.8 3.7.2 2.6.9 3.3.7 2.7.15 3.2.6 3.1.5 3.4.8'

0
admin-tools/setup-master.sh Normal file → Executable file
View File

0
admin-tools/setup-python-2.4.sh Normal file → Executable file
View File

View File

@@ -1,3 +0,0 @@
#!/bin/bash
cd $(dirname ${BASH_SOURCE[0]})/..
git pull

View File

@@ -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):

View File

@@ -10,7 +10,7 @@ else:
maxint = sys.maxint
from uncompyle6.semantics.helper import print_docstring
class PrintFake:
class PrintFake():
def __init__(self):
self.pending_newlines = 0
self.f = StringIO()

View File

@@ -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)

154
pytest/test_fstring.py Normal file
View File

@@ -0,0 +1,154 @@
# std
# test
from uncompyle6 import PYTHON_VERSION, deparse_code
import pytest
pytestmark = pytest.mark.skipif(PYTHON_VERSION <= 2.6,
reason='hypothesis needs 2.7 or later')
if PYTHON_VERSION > 2.6:
import hypothesis
from hypothesis import strategies as st
# uncompyle6
@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()',
# These expressions are failing, I think these are control
# flow problems rather than problems with FORMAT_VALUE,
# however I need to confirm this...
#'sorted(items, key=lambda x: x.name)',
#'func(*args, **kwargs)',
#'text or default',
#'43 if life_the_universe and everything else None'
)))
@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.
"""
character_strategy = st.characters(
blacklist_characters='\r\n\'\\s{}',
min_codepoint=1,
max_codepoint=1000,
)
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())
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.append(draw(st.text(character_strategy)))
content = ''.join(content)
return "f{}'{}'".format('r' if is_raw else '', content)
@pytest.mark.skipif(PYTHON_VERSION != 3.6, reason='need 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
def run_test(text):
hypothesis.assume(len(text))
hypothesis.assume("f'{" in text)
expr = text + '\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 'dis(' + deparsed.text.strip('\n') + ')' == 'dis(' + expr.strip('\n') + ')'
@pytest.mark.skipif(PYTHON_VERSION != 3.6, reason='need Python 3.6')
@hypothesis.given(fstrings())
def test_uncompyle_fstring(fstring):
"""Verify uncompyling fstring bytecode"""
run_test(fstring)
@pytest.mark.skipif(PYTHON_VERSION < 3.6, reason='need Python 3.6+')
@pytest.mark.parametrize('fstring', [
"f'{abc}{abc!s}'",
"f'{abc}0'",
])
def test_uncompyle_direct(fstring):
"""useful for debugging"""
run_test(fstring)

View File

@@ -0,0 +1,185 @@
import string
from uncompyle6 import PYTHON_VERSION
import pytest
pytestmark = pytest.mark.skip(PYTHON_VERSION < 2.7,
reason="need at least Python 2.7")
if PYTHON_VERSION > 2.6:
from hypothesis import given, assume, example, settings, strategies as st
from validate import validate_uncompyle
from test_fstring import expressions
alpha = st.sampled_from(string.ascii_lowercase)
numbers = st.sampled_from(string.digits)
alphanum = st.sampled_from(string.ascii_lowercase + string.digits)
@st.composite
def function_calls(draw,
min_keyword_args=0, max_keyword_args=5,
min_positional_args=0, max_positional_args=5,
min_star_args=0, max_star_args=1,
min_double_star_args=0, max_double_star_args=1):
"""
Strategy factory for generating function calls.
:param draw: Callable which draws examples from other strategies.
:return: The function call text.
"""
st_positional_args = st.lists(
alpha,
min_size=min_positional_args,
max_size=max_positional_args
)
st_keyword_args = st.lists(
alpha,
min_size=min_keyword_args,
max_size=max_keyword_args
)
st_star_args = st.lists(
alpha,
min_size=min_star_args,
max_size=max_star_args
)
st_double_star_args = st.lists(
alpha,
min_size=min_double_star_args,
max_size=max_double_star_args
)
positional_args = draw(st_positional_args)
keyword_args = draw(st_keyword_args)
st_values = st.lists(
expressions(),
min_size=len(keyword_args),
max_size=len(keyword_args)
)
keyword_args = [
x + '=' + e
for x, e in
zip(keyword_args, draw(st_values))
]
star_args = ['*' + x for x in draw(st_star_args)]
double_star_args = ['**' + x for x in draw(st_double_star_args)]
arguments = positional_args + keyword_args + star_args + double_star_args
draw(st.randoms()).shuffle(arguments)
arguments = ','.join(arguments)
function_call = 'fn({arguments})'.format(arguments=arguments)
try:
# TODO: Figure out the exact rules for ordering of positional, keyword,
# star args, double star args and in which versions the various
# types of arguments are supported so we don't need to check that the
# expression compiles like this.
compile(function_call, '<string>', 'single')
except:
assume(False)
return function_call
def test_function_no_args():
validate_uncompyle("fn()")
@pytest.mark.skipif(PYTHON_VERSION < 2.7,
reason="need at least Python 2.7")
def isolated_function_calls(which):
"""
Returns a strategy for generating function calls, but isolated to
particular types of arguments, for example only positional arguments.
This can help reason about debugging errors in specific types of function
calls.
:param which: One of 'keyword', 'positional', 'star', 'double_star'
:return: Strategy for generating an function call isolated to specific
argument types.
"""
kwargs = dict(
max_keyword_args=0,
max_positional_args=0,
max_star_args=0,
max_double_star_args=0,
)
kwargs['_'.join(('min', which, 'args'))] = 1
kwargs['_'.join(('max', which, 'args'))] = 5 if 'star' not in which else 1
return function_calls(**kwargs)
with settings(max_examples=25):
@pytest.mark.skipif(PYTHON_VERSION < 2.7,
reason="need at least Python 2.7")
@given(isolated_function_calls('positional'))
@example("fn(0)")
def test_function_positional_only(expr):
validate_uncompyle(expr)
@pytest.mark.skipif(PYTHON_VERSION < 2.7,
reason="need at least Python 2.7")
@given(isolated_function_calls('keyword'))
@example("fn(a=0)")
def test_function_call_keyword_only(expr):
validate_uncompyle(expr)
@pytest.mark.skipif(PYTHON_VERSION < 2.7,
reason="need at least Python 2.7")
@given(isolated_function_calls('star'))
@example("fn(*items)")
def test_function_call_star_only(expr):
validate_uncompyle(expr)
@pytest.mark.skipif(PYTHON_VERSION < 2.7,
reason="need at least Python 2.7")
@given(isolated_function_calls('double_star'))
@example("fn(**{})")
def test_function_call_double_star_only(expr):
validate_uncompyle(expr)
@pytest.mark.xfail()
def test_BUILD_CONST_KEY_MAP_BUILD_MAP_UNPACK_WITH_CALL_BUILD_TUPLE_CALL_FUNCTION_EX():
validate_uncompyle("fn(w=0,m=0,**v)")
@pytest.mark.xfail()
def test_BUILD_MAP_BUILD_MAP_UNPACK_WITH_CALL_BUILD_TUPLE_CALL_FUNCTION_EX():
validate_uncompyle("fn(a=0,**g)")
@pytest.mark.xfail()
def test_CALL_FUNCTION_EX():
validate_uncompyle("fn(*g,**j)")
@pytest.mark.xfail()
def test_BUILD_MAP_CALL_FUNCTION_EX():
validate_uncompyle("fn(*z,u=0)")
@pytest.mark.xfail()
def test_BUILD_TUPLE_CALL_FUNCTION_EX():
validate_uncompyle("fn(**a)")
@pytest.mark.xfail()
def test_BUILD_MAP_BUILD_TUPLE_BUILD_TUPLE_UNPACK_WITH_CALL_CALL_FUNCTION_EX():
validate_uncompyle("fn(b,b,b=0,*a)")
@pytest.mark.xfail()
def test_BUILD_TUPLE_BUILD_TUPLE_UNPACK_WITH_CALL_CALL_FUNCTION_EX():
validate_uncompyle("fn(*c,v)")
@pytest.mark.xfail()
def test_BUILD_CONST_KEY_MAP_CALL_FUNCTION_EX():
validate_uncompyle("fn(i=0,y=0,*p)")
@pytest.mark.skip(reason='skipping property based test until all individual tests are passing')
@given(function_calls())
def test_function_call(function_call):
validate_uncompyle(function_call)

View File

@@ -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 as SourceWalker
@@ -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]

View File

@@ -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():

View File

@@ -9,4 +9,4 @@
12 JUMP_FORWARD 0 'to 15'
15_0 COME_FROM 12 '12'
15 LOAD_CONST 0 None
18 RETURN_VALUE
18 RETURN_VALUE

View File

@@ -12,4 +12,4 @@
18 STORE_NAME 2 'd'
21_0 COME_FROM 12 '12'
21 LOAD_CONST 2 None
24 RETURN_VALUE
24 RETURN_VALUE

View File

@@ -1,25 +1,28 @@
# future
from __future__ import print_function
# std
import os
import difflib
import subprocess
import tempfile
from StringIO import StringIO
import functools
# uncompyle6 / xdis
from uncompyle6 import PYTHON_VERSION, IS_PYPY, deparse_code
from uncompyle6 import PYTHON_VERSION, PYTHON3, IS_PYPY, deparse_code
# TODO : I think we can get xdis to support the dis api (python 3 version) by doing something like this there
from xdis.bytecode import Bytecode
from xdis.main import get_opcode
opc = get_opcode(PYTHON_VERSION, IS_PYPY)
from StringIO import StringIO
Bytecode = functools.partial(Bytecode, opc=opc)
import six
if PYTHON3:
from io import StringIO
else:
from StringIO import StringIO
def _dis_to_text(co):
return Bytecode(co).dis()
try:
import functools
Bytecode = functools.partial(Bytecode, opc=opc)
def _dis_to_text(co):
return Bytecode(co).dis()
except:
pass
def print_diff(original, uncompyled):
"""
@@ -42,11 +45,8 @@ def print_diff(original, uncompyled):
print('\nTo display diff highlighting run:\n pip install BeautifulSoup4')
diff = difflib.HtmlDiff().make_table(*args)
f = tempfile.NamedTemporaryFile(delete=False)
try:
with tempfile.NamedTemporaryFile(delete=False) as f:
f.write(str(diff).encode('utf-8'))
finally:
f.close()
try:
print()
@@ -63,7 +63,8 @@ def print_diff(original, uncompyled):
print('\nFor side by side diff install elinks')
diff = difflib.Differ().compare(original_lines, uncompyled_lines)
print('\n'.join(diff))
os.unlink(f.name)
finally:
os.unlink(f.name)
def are_instructions_equal(i1, i2):
@@ -125,9 +126,8 @@ def validate_uncompyle(text, mode='exec'):
original_text = text
deparsed = deparse_code(PYTHON_VERSION, original_code,
compile_mode=mode,
out=StringIO(),
out=six.StringIO(),
is_pypy=IS_PYPY)
uncompyled_text = deparsed.text
uncompyled_code = compile(uncompyled_text, '<string>', 'exec')

View File

@@ -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, 8)):
mess = "Python Release 2.6 .. 3.8 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)

View File

@@ -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(['expr1024', 'pos_arg'])
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()

View File

@@ -29,7 +29,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
@@ -148,7 +148,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
@@ -264,8 +263,8 @@ check-bytecode-3.5:
#: Check deparsing Python 3.6
check-bytecode-3.6:
$(PYTHON) test_pythonlib.py --bytecode-3.6 --weak-verify
$(PYTHON) test_pythonlib.py --bytecode-3.6-run --verify-run
$(PYTHON) test_pythonlib.py --bytecode-3.6 --weak-verify
#: Check deparsing Python 3.7
check-bytecode-3.7:
@@ -273,6 +272,7 @@ check-bytecode-3.7:
#: 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 --weak-verify
#: short tests for bytecodes only for this version of Python
@@ -280,10 +280,6 @@ check-native-short:
$(PYTHON) test_pythonlib.py --bytecode-$(PYTHON_VERSION) --weak-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 --weak-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.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

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

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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()

View File

@@ -1,12 +1,18 @@
# Python 2.7 sqlalchemy-1.013/sql/crud.py
def _extend_values_for_multiparams(compiler, stmt, c):
c(
[
(
(compiler() if compiler()
else compiler())
if c in stmt else compiler(),
)
]
for i in enumerate(stmt)
# Adapted from Python 2.7 sqlalchemy-1.013/sql/crud.py
# Bug was in handling generator comprehension
# In 2.6, 2.7 JUMP_ABSOLUTEs rather than JUMP_BACKs are generated
# RUNNABLE!
def extend(stmt, a, c, c1, c2, c3):
return c(
([ (5 if c1 else c2)
if a else c3
] for i in enumerate(stmt))
)
def foo(gen):
return list(gen)
assert extend([0], 0, foo, True, 'c2', 'c3') == [['c3']]
assert extend([0, 1], 1, foo, False, 'c2', 'c3') == [['c2'], ['c2']]
assert extend([0, 1], False, foo, False, 'c2', 'c3') == [['c3'], ['c3']]

View File

@@ -1,8 +1,11 @@
# In Python 3.3+ this uses grammar rule
# compare_chained2 ::= expr COMPARE_OP RETURN_VALUE
# In Python 3.6 uses this uses grammar rule
# compare_chained2 ::= expr COMPARE_OP come_froms JUMP_FORWARD
# Seen in Python 3.3 ipaddress.py
# RUNNABLE!
def _is_valid_netmask(netmask):
return 0 <= netmask <= 10
@@ -10,4 +13,4 @@ def _is_valid_netmask(netmask):
# detections
# See in 2.6.9 quopri.py ishex():
'0' <= __file__ <= '9' or 'a' <= __file__ <= 'f' or 'A' <= __file__ <= 'F'
assert not '0' <= __file__ <= '9' or 'a' <= __file__ <= 'f' or 'A' <= __file__ <= 'F'

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