You've already forked python-uncompyle6
mirror of
https://github.com/rocky/python-uncompyle6.git
synced 2025-08-03 16:59:52 +08:00
Run black over validate.py
This commit is contained in:
@@ -1,16 +1,20 @@
|
|||||||
# future
|
# future
|
||||||
from __future__ import print_function
|
from __future__ import print_function
|
||||||
|
|
||||||
# std
|
# std
|
||||||
import os
|
import os
|
||||||
import difflib
|
import difflib
|
||||||
import subprocess
|
import subprocess
|
||||||
import tempfile
|
import tempfile
|
||||||
import functools
|
import functools
|
||||||
|
|
||||||
# uncompyle6 / xdis
|
# uncompyle6 / xdis
|
||||||
from uncompyle6 import PYTHON_VERSION, PYTHON3, IS_PYPY, code_deparse
|
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
|
||||||
|
|
||||||
opc = get_opcode(PYTHON_VERSION, IS_PYPY)
|
opc = get_opcode(PYTHON_VERSION, IS_PYPY)
|
||||||
Bytecode = functools.partial(Bytecode, opc=opc)
|
Bytecode = functools.partial(Bytecode, opc=opc)
|
||||||
import six
|
import six
|
||||||
@@ -20,6 +24,7 @@ if PYTHON3:
|
|||||||
else:
|
else:
|
||||||
from StringIO import StringIO
|
from StringIO import StringIO
|
||||||
|
|
||||||
|
|
||||||
def _dis_to_text(co):
|
def _dis_to_text(co):
|
||||||
return Bytecode(co).dis()
|
return Bytecode(co).dis()
|
||||||
|
|
||||||
@@ -33,36 +38,32 @@ def print_diff(original, uncompyled):
|
|||||||
:param original: Text describing the original code object.
|
:param original: Text describing the original code object.
|
||||||
:param uncompyled: Text describing the uncompyled code object.
|
:param uncompyled: Text describing the uncompyled code object.
|
||||||
"""
|
"""
|
||||||
original_lines = original.split('\n')
|
original_lines = original.split("\n")
|
||||||
uncompyled_lines = uncompyled.split('\n')
|
uncompyled_lines = uncompyled.split("\n")
|
||||||
args = original_lines, uncompyled_lines, 'original', 'uncompyled'
|
args = original_lines, uncompyled_lines, "original", "uncompyled"
|
||||||
try:
|
try:
|
||||||
from bs4 import BeautifulSoup
|
from bs4 import BeautifulSoup
|
||||||
|
|
||||||
diff = difflib.HtmlDiff().make_file(*args)
|
diff = difflib.HtmlDiff().make_file(*args)
|
||||||
diff = BeautifulSoup(diff, "html.parser")
|
diff = BeautifulSoup(diff, "html.parser")
|
||||||
diff.select_one('table[summary="Legends"]').extract()
|
diff.select_one('table[summary="Legends"]').extract()
|
||||||
except ImportError:
|
except ImportError:
|
||||||
print('\nTo display diff highlighting run:\n pip install BeautifulSoup4')
|
print("\nTo display diff highlighting run:\n pip install BeautifulSoup4")
|
||||||
diff = difflib.HtmlDiff().make_table(*args)
|
diff = difflib.HtmlDiff().make_table(*args)
|
||||||
|
|
||||||
with tempfile.NamedTemporaryFile(delete=False) as f:
|
with tempfile.NamedTemporaryFile(delete=False) as f:
|
||||||
f.write(str(diff).encode('utf-8'))
|
f.write(str(diff).encode("utf-8"))
|
||||||
|
|
||||||
try:
|
try:
|
||||||
print()
|
print()
|
||||||
html = subprocess.check_output([
|
html = subprocess.check_output(
|
||||||
'elinks',
|
["elinks", "-dump", "-no-references", "-dump-color-mode", "1", f.name]
|
||||||
'-dump',
|
).decode("utf-8")
|
||||||
'-no-references',
|
|
||||||
'-dump-color-mode',
|
|
||||||
'1',
|
|
||||||
f.name,
|
|
||||||
]).decode('utf-8')
|
|
||||||
print(html)
|
print(html)
|
||||||
except:
|
except:
|
||||||
print('\nFor side by side diff install elinks')
|
print("\nFor side by side diff install elinks")
|
||||||
diff = difflib.Differ().compare(original_lines, uncompyled_lines)
|
diff = difflib.Differ().compare(original_lines, uncompyled_lines)
|
||||||
print('\n'.join(diff))
|
print("\n".join(diff))
|
||||||
finally:
|
finally:
|
||||||
os.unlink(f.name)
|
os.unlink(f.name)
|
||||||
|
|
||||||
@@ -80,18 +81,19 @@ def are_instructions_equal(i1, i2):
|
|||||||
|
|
||||||
:return: True if the two instructions are approximately equal, otherwise False.
|
:return: True if the two instructions are approximately equal, otherwise False.
|
||||||
"""
|
"""
|
||||||
result = (1 == 1
|
result = (
|
||||||
|
1 == 1
|
||||||
and i1.opname == i2.opname
|
and i1.opname == i2.opname
|
||||||
and i1.opcode == i2.opcode
|
and i1.opcode == i2.opcode
|
||||||
and i1.arg == i2.arg
|
and i1.arg == i2.arg
|
||||||
# ignore differences due to code objects
|
# ignore differences due to code objects
|
||||||
# TODO : Better way of ignoring address
|
# TODO : Better way of ignoring address
|
||||||
and (i1.argval == i2.argval or '<code object' in str(i1.argval))
|
and (i1.argval == i2.argval or "<code object" in str(i1.argval))
|
||||||
# TODO : Should probably recurse to check code objects
|
# TODO : Should probably recurse to check code objects
|
||||||
and (i1.argrepr == i2.argrepr or '<code object' in i1.argrepr)
|
and (i1.argrepr == i2.argrepr or "<code object" in i1.argrepr)
|
||||||
and i1.offset == i2.offset
|
and i1.offset == i2.offset
|
||||||
# ignore differences in line numbers
|
# ignore differences in line numbers
|
||||||
#and i1.starts_line
|
# and i1.starts_line
|
||||||
and i1.is_jump_target == i2.is_jump_target
|
and i1.is_jump_target == i2.is_jump_target
|
||||||
)
|
)
|
||||||
return result
|
return result
|
||||||
@@ -115,22 +117,21 @@ def are_code_objects_equal(co1, co2):
|
|||||||
return True
|
return True
|
||||||
|
|
||||||
|
|
||||||
def validate_uncompyle(text, mode='exec'):
|
def validate_uncompyle(text, mode="exec"):
|
||||||
"""
|
"""
|
||||||
Validate decompilation of the given source code.
|
Validate decompilation of the given source code.
|
||||||
|
|
||||||
:param text: Source to validate decompilation of.
|
:param text: Source to validate decompilation of.
|
||||||
"""
|
"""
|
||||||
original_code = compile(text, '<string>', mode)
|
original_code = compile(text, "<string>", mode)
|
||||||
original_dis = _dis_to_text(original_code)
|
original_dis = _dis_to_text(original_code)
|
||||||
original_text = text
|
original_text = text
|
||||||
|
|
||||||
deparsed = code_deparse(original_code,
|
deparsed = code_deparse(
|
||||||
out=six.StringIO(),
|
original_code, out=six.StringIO(), version=PYTHON_VERSION, compile_mode=mode
|
||||||
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")
|
||||||
|
|
||||||
if not are_code_objects_equal(uncompyled_code, original_code):
|
if not are_code_objects_equal(uncompyled_code, original_code):
|
||||||
|
|
||||||
@@ -138,15 +139,17 @@ def validate_uncompyle(text, mode='exec'):
|
|||||||
|
|
||||||
def output(text, dis):
|
def output(text, dis):
|
||||||
width = 60
|
width = 60
|
||||||
return '\n\n'.join([
|
return "\n\n".join(
|
||||||
' SOURCE CODE '.center(width, '#'),
|
[
|
||||||
text.strip(),
|
" SOURCE CODE ".center(width, "#"),
|
||||||
' BYTECODE '.center(width, '#'),
|
text.strip(),
|
||||||
dis
|
" BYTECODE ".center(width, "#"),
|
||||||
])
|
dis,
|
||||||
|
]
|
||||||
|
)
|
||||||
|
|
||||||
original = output(original_text, original_dis)
|
original = output(original_text, original_dis)
|
||||||
uncompyled = output(uncompyled_text, uncompyled_dis)
|
uncompyled = output(uncompyled_text, uncompyled_dis)
|
||||||
print_diff(original, uncompyled)
|
print_diff(original, uncompyled)
|
||||||
|
|
||||||
assert 'original' == 'uncompyled'
|
assert "original" == "uncompyled"
|
||||||
|
Reference in New Issue
Block a user