remove deprecated deparse_code

This commit is contained in:
rocky
2019-06-16 21:57:56 -04:00
parent 4b82806d6c
commit d369017122
4 changed files with 71 additions and 93 deletions

View File

@@ -1,9 +1,12 @@
# std # std
# test # test
from uncompyle6 import PYTHON_VERSION, deparse_code import sys
from uncompyle6 import PYTHON_VERSION, code_deparse
import pytest import pytest
pytestmark = pytest.mark.skipif(PYTHON_VERSION <= 2.6,
reason='hypothesis needs 2.7 or later') pytestmark = pytest.mark.skipif(
PYTHON_VERSION <= 2.6, reason="hypothesis needs 2.7 or later"
)
if PYTHON_VERSION > 2.6: if PYTHON_VERSION > 2.6:
import hypothesis import hypothesis
@@ -11,29 +14,31 @@ if PYTHON_VERSION > 2.6:
# uncompyle6 # uncompyle6
@st.composite @st.composite
def expressions(draw): def expressions(draw):
# todo : would be nice to generate expressions using hypothesis however # todo : would be nice to generate expressions using hypothesis however
# this is pretty involved so for now just use a corpus of expressions # this is pretty involved so for now just use a corpus of expressions
# from which to select. # from which to select.
return draw(st.sampled_from(( return draw(
'abc', st.sampled_from(
'len(items)', (
'x + 1', "abc",
'lineno', "len(items)",
'container', "x + 1",
'self.attribute', "lineno",
'self.method()', "container",
# These expressions are failing, I think these are control "self.attribute",
# flow problems rather than problems with FORMAT_VALUE, "self.method()",
# however I need to confirm this... # These expressions are failing, I think these are control
#'sorted(items, key=lambda x: x.name)', # flow problems rather than problems with FORMAT_VALUE,
#'func(*args, **kwargs)', # however I need to confirm this...
#'text or default', #'sorted(items, key=lambda x: x.name)',
#'43 if life_the_universe and everything else None' #'func(*args, **kwargs)',
))) #'text or default',
#'43 if life_the_universe and everything else None'
)
)
)
@st.composite @st.composite
def format_specifiers(draw): def format_specifiers(draw):
@@ -54,36 +59,37 @@ if PYTHON_VERSION > 2.6:
:return: An example format_specifier. :return: An example format_specifier.
""" """
alphabet_strategy = st.characters(min_codepoint=ord('a'), max_codepoint=ord('z')) alphabet_strategy = st.characters(
min_codepoint=ord("a"), max_codepoint=ord("z")
)
fill = draw(st.one_of(alphabet_strategy, st.none())) fill = draw(st.one_of(alphabet_strategy, st.none()))
align = draw(st.sampled_from(list('<>=^'))) align = draw(st.sampled_from(list("<>=^")))
fill_align = (fill + align or '') if fill else '' fill_align = (fill + align or "") if fill else ""
type_ = draw(st.sampled_from('bcdeEfFgGnosxX%')) type_ = draw(st.sampled_from("bcdeEfFgGnosxX%"))
can_have_sign = type_ in 'deEfFgGnoxX%' can_have_sign = type_ in "deEfFgGnoxX%"
can_have_comma = type_ in 'deEfFgG%' can_have_comma = type_ in "deEfFgG%"
can_have_precision = type_ in 'fFgG' can_have_precision = type_ in "fFgG"
can_have_pound = type_ in 'boxX%' can_have_pound = type_ in "boxX%"
can_have_zero = type_ in 'oxX' can_have_zero = type_ in "oxX"
sign = draw(st.sampled_from(list('+- ') + [''])) if can_have_sign else '' sign = draw(st.sampled_from(list("+- ") + [""])) if can_have_sign else ""
pound = draw(st.sampled_from(('#', '',))) if can_have_pound else '' pound = draw(st.sampled_from(("#", ""))) if can_have_pound else ""
zero = draw(st.sampled_from(('0', '',))) if can_have_zero else '' zero = draw(st.sampled_from(("0", ""))) if can_have_zero else ""
int_strategy = st.integers(min_value=1, max_value=1000) int_strategy = st.integers(min_value=1, max_value=1000)
width = draw(st.one_of(int_strategy, st.none())) width = draw(st.one_of(int_strategy, st.none()))
width = str(width) if width is not None else '' width = str(width) if width is not None else ""
comma = draw(st.sampled_from((',', '',))) if can_have_comma else '' comma = draw(st.sampled_from((",", ""))) if can_have_comma else ""
if can_have_precision: if can_have_precision:
precision = draw(st.one_of(int_strategy, st.none())) precision = draw(st.one_of(int_strategy, st.none()))
precision = '.' + str(precision) if precision else '' precision = "." + str(precision) if precision else ""
else: else:
precision = '' precision = ""
return ''.join((fill_align, sign, pound, zero, width, comma, precision, type_,))
return "".join((fill_align, sign, pound, zero, width, comma, precision, type_))
@st.composite @st.composite
def fstrings(draw): def fstrings(draw):
@@ -96,9 +102,7 @@ if PYTHON_VERSION > 2.6:
:return: A valid f-string. :return: A valid f-string.
""" """
character_strategy = st.characters( character_strategy = st.characters(
blacklist_characters='\r\n\'\\s{}', blacklist_characters="\r\n'\\s{}", min_codepoint=1, max_codepoint=1000
min_codepoint=1,
max_codepoint=1000,
) )
is_raw = draw(st.booleans()) is_raw = draw(st.booleans())
integer_strategy = st.integers(min_value=0, max_value=3) integer_strategy = st.integers(min_value=0, max_value=3)
@@ -106,53 +110,49 @@ if PYTHON_VERSION > 2.6:
content = [] content = []
for _ in range(expression_count): for _ in range(expression_count):
expression = draw(expressions()) expression = draw(expressions())
conversion = draw(st.sampled_from(('', '!s', '!r', '!a',))) conversion = draw(st.sampled_from(("", "!s", "!r", "!a")))
has_specifier = draw(st.booleans()) has_specifier = draw(st.booleans())
specifier = ':' + draw(format_specifiers()) if has_specifier else '' specifier = ":" + draw(format_specifiers()) if has_specifier else ""
content.append('{{{}{}}}'.format(expression, conversion, specifier)) content.append("{{{}{}}}".format(expression, conversion, specifier))
content.append(draw(st.text(character_strategy))) content.append(draw(st.text(character_strategy)))
content = ''.join(content) content = "".join(content)
return "f{}'{}'".format('r' if is_raw else '', content) return "f{}'{}'".format("r" if is_raw else "", content)
@pytest.mark.skipif(PYTHON_VERSION != 3.6, reason="need Python 3.6")
@pytest.mark.skipif(PYTHON_VERSION != 3.6, reason='need Python 3.6')
@hypothesis.given(format_specifiers()) @hypothesis.given(format_specifiers())
def test_format_specifiers(format_specifier): def test_format_specifiers(format_specifier):
"""Verify that format_specifiers generates valid specifiers""" """Verify that format_specifiers generates valid specifiers"""
try: try:
exec('"{:' + format_specifier + '}".format(0)') exec('"{:' + format_specifier + '}".format(0)')
except ValueError as e: except ValueError as e:
if 'Unknown format code' not in str(e): if "Unknown format code" not in str(e):
raise raise
def run_test(text): def run_test(text):
hypothesis.assume(len(text)) hypothesis.assume(len(text))
hypothesis.assume("f'{" in text) hypothesis.assume("f'{" in text)
expr = text + '\n' expr = text + "\n"
code = compile(expr, '<string>', 'single') code = compile(expr, "<string>", "single")
deparsed = deparse_code(PYTHON_VERSION, code, compile_mode='single') deparsed = code_deparse(code, sys.stdout, PYTHON_VERSION, compile_mode="single")
recompiled = compile(deparsed.text, '<string>', 'single') recompiled = compile(deparsed.text, "<string>", "single")
if recompiled != code: if recompiled != code:
print(recompiled) print(recompiled)
print('================') print("================")
print(code) print(code)
print('----------------') print("----------------")
assert 'dis(' + deparsed.text.strip('\n') + ')' == 'dis(' + expr.strip('\n') + ')' assert (
"dis(" + deparsed.text.strip("\n") + ")"
== "dis(" + expr.strip("\n") + ")"
)
@pytest.mark.skipif(PYTHON_VERSION != 3.6, reason="need Python 3.6")
@pytest.mark.skipif(PYTHON_VERSION != 3.6, reason='need Python 3.6')
@hypothesis.given(fstrings()) @hypothesis.given(fstrings())
def test_uncompyle_fstring(fstring): def test_uncompyle_fstring(fstring):
"""Verify uncompyling fstring bytecode""" """Verify uncompyling fstring bytecode"""
run_test(fstring) run_test(fstring)
@pytest.mark.skipif(PYTHON_VERSION != 3.6, reason="need Python 3.6+")
@pytest.mark.skipif(PYTHON_VERSION != 3.6, reason='need Python 3.6+') @pytest.mark.parametrize("fstring", ["f'{abc}{abc!s}'", "f'{abc}0'"])
@pytest.mark.parametrize('fstring', [
"f'{abc}{abc!s}'",
"f'{abc}0'",
])
def test_uncompyle_direct(fstring): def test_uncompyle_direct(fstring):
"""useful for debugging""" """useful for debugging"""
run_test(fstring) run_test(fstring)

View File

@@ -7,7 +7,7 @@ import subprocess
import tempfile import tempfile
import functools import functools
# uncompyle6 / xdis # uncompyle6 / xdis
from uncompyle6 import PYTHON_VERSION, PYTHON3, IS_PYPY, deparse_code from uncompyle6 import PYTHON_VERSION, PYTHON3, IS_PYPY, code_deparse
# TODO : I think we can get xdis to support the dis api (python 3 version) by doing something like this there # 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.bytecode import Bytecode
from xdis.main import get_opcode from xdis.main import get_opcode
@@ -125,10 +125,10 @@ def validate_uncompyle(text, mode='exec'):
original_dis = _dis_to_text(original_code) original_dis = _dis_to_text(original_code)
original_text = text original_text = text
deparsed = deparse_code(PYTHON_VERSION, original_code, deparsed = code_deparse(original_code,
compile_mode=mode,
out=six.StringIO(), out=six.StringIO(),
is_pypy=IS_PYPY) version=PYTHON_VERSION,
compile_mode=mode)
uncompyled_text = deparsed.text uncompyled_text = deparsed.text
uncompyled_code = compile(uncompyled_text, '<string>', 'exec') uncompyled_code = compile(uncompyled_text, '<string>', 'exec')

View File

@@ -51,14 +51,8 @@ import uncompyle6.semantics.fragments
# Export some functions # Export some functions
from uncompyle6.main import decompile_file from uncompyle6.main import decompile_file
# For compatibility
uncompyle_file = decompile_file
# Convenience functions so you can say: # Convenience functions so you can say:
# from uncompyle6 import (code_deparse, deparse_code2str) # from uncompyle6 import (code_deparse, deparse_code2str)
code_deparse = uncompyle6.semantics.pysource.code_deparse
deparse_code2str = uncompyle6.semantics.pysource.deparse_code2str deparse_code2str = uncompyle6.semantics.pysource.deparse_code2str
code_deparse = uncompyle6.semantics.pysource.code_deparse
# This is deprecated:
deparse_code = uncompyle6.semantics.pysource.deparse_code

View File

@@ -2269,22 +2269,6 @@ DEFAULT_DEBUG_OPTS = {
'grammar': False 'grammar': False
} }
# This interface is deprecated. Use simpler code_deparse.
def deparse_code(version, co, out=sys.stdout, showasm=None, showast=False,
showgrammar=False, code_objects={}, compile_mode='exec',
is_pypy=IS_PYPY, walker=SourceWalker):
debug_opts = {
'asm': showasm,
'ast': showast,
'grammar': showgrammar
}
return code_deparse(co, out,
version=version,
debug_opts=debug_opts,
code_objects=code_objects,
compile_mode=compile_mode,
is_pypy=is_pypy, walker=walker)
def code_deparse(co, out=sys.stdout, version=None, debug_opts=DEFAULT_DEBUG_OPTS, def code_deparse(co, out=sys.stdout, version=None, debug_opts=DEFAULT_DEBUG_OPTS,
code_objects={}, compile_mode='exec', is_pypy=IS_PYPY, walker=SourceWalker): code_objects={}, compile_mode='exec', is_pypy=IS_PYPY, walker=SourceWalker):
""" """