Merge branch 'python-3.3-to-3.5' into python-3.0-to-3.2

This commit is contained in:
rocky
2023-03-25 02:28:32 -04:00
9 changed files with 80 additions and 81 deletions

1
.github/ISSUE_TEMPLATE/config.yml vendored Normal file
View File

@@ -0,0 +1 @@
blank_issues_enabled: False

View File

@@ -75,7 +75,7 @@ entry_points = {
] ]
} }
ftp_url = None ftp_url = None
install_requires = ["spark-parser >= 1.8.9, < 1.9.0", "xdis >= 6.0.2, < 6.1.0"] install_requires = ["spark-parser >= 1.8.9, < 1.9.0", "xdis >= 6.0.2, < 6.2.0"]
license = "GPL3" license = "GPL3"
mailing_list = "python-debugger@googlegroups.com" mailing_list = "python-debugger@googlegroups.com"

View File

@@ -29,11 +29,18 @@ Step 2: Run the test:
from __future__ import print_function from __future__ import print_function
import getopt, os, py_compile, sys, shutil, tempfile, time import getopt
import os
import py_compile
import shutil
import sys
import tempfile
import time
from fnmatch import fnmatch from fnmatch import fnmatch
from xdis.version_info import PYTHON_VERSION_TRIPLE
from uncompyle6.main import main from uncompyle6.main import main
from xdis.version_info import PYTHON_VERSION
def get_srcdir(): def get_srcdir():
@@ -164,10 +171,10 @@ def do_tests(src_dir, obj_patterns, target_dir, opts):
if opts["do_compile"]: if opts["do_compile"]:
compiled_version = opts["compiled_version"] compiled_version = opts["compiled_version"]
if compiled_version and PYTHON_VERSION != compiled_version: if compiled_version and PYTHON_VERSION_TRIPLE != compiled_version:
print( print(
"Not compiling: desired Python version is %s but we are running %s" "Not compiling: desired Python version is %s but we are running %s"
% (compiled_version, PYTHON_VERSION), % (compiled_version, PYTHON_VERSION_TRIPLE),
file=sys.stderr, file=sys.stderr,
) )
else: else:

View File

@@ -1,4 +1,4 @@
# Copyright (c) 2016-2017, 2019-2020, 2022 Rocky Bernstein # Copyright (c) 2016-2017, 2019-2020, 2022-2023 Rocky Bernstein
""" """
Python 3.7 base code. We keep non-custom-generated grammar rules out of this file. Python 3.7 base code. We keep non-custom-generated grammar rules out of this file.
""" """
@@ -431,35 +431,39 @@ class Python37BaseParser(PythonParser):
"BUILD_TUPLE", "BUILD_TUPLE",
"BUILD_TUPLE_UNPACK", "BUILD_TUPLE_UNPACK",
): ):
v = token.attr collection_size = token.attr
is_LOAD_CLOSURE = False is_LOAD_CLOSURE = False
if opname_base == "BUILD_TUPLE": if opname_base == "BUILD_TUPLE":
# If is part of a "load_closure", then it is not part of a # If is part of a "load_closure", then it is not part of a
# "list". # "list".
is_LOAD_CLOSURE = True is_LOAD_CLOSURE = True
for j in range(v): for j in range(collection_size):
if tokens[i - j - 1].kind != "LOAD_CLOSURE": if tokens[i - j - 1].kind != "LOAD_CLOSURE":
is_LOAD_CLOSURE = False is_LOAD_CLOSURE = False
break break
if is_LOAD_CLOSURE: if is_LOAD_CLOSURE:
rule = "load_closure ::= %s%s" % (("LOAD_CLOSURE " * v), opname) rule = "load_closure ::= %s%s" % (
("LOAD_CLOSURE " * collection_size),
opname,
)
self.add_unique_rule(rule, opname, token.attr, customize) self.add_unique_rule(rule, opname, token.attr, customize)
if not is_LOAD_CLOSURE or v == 0: if not is_LOAD_CLOSURE or collection_size == 0:
# We do this complicated test to speed up parsing of # We do this complicated test to speed up parsing of
# pathelogically long literals, especially those over 1024. # pathelogically long literals, especially those over 1024.
build_count = token.attr thousands = collection_size // 1024
thousands = build_count // 1024 thirty32s = (collection_size // 32) % 32
thirty32s = (build_count // 32) % 32
if thirty32s > 0: if thirty32s > 0:
rule = "expr32 ::=%s" % (" expr" * 32) rule = "expr32 ::=%s" % (" expr" * 32)
self.add_unique_rule(rule, opname_base, build_count, customize) self.add_unique_rule(
rule, opname_base, collection_size, customize
)
pass pass
if thousands > 0: if thousands > 0:
self.add_unique_rule( self.add_unique_rule(
"expr1024 ::=%s" % (" expr32" * 32), "expr1024 ::=%s" % (" expr32" * 32),
opname_base, opname_base,
build_count, collection_size,
customize, customize,
) )
pass pass
@@ -468,7 +472,7 @@ class Python37BaseParser(PythonParser):
("%s ::= " % collection) ("%s ::= " % collection)
+ "expr1024 " * thousands + "expr1024 " * thousands
+ "expr32 " * thirty32s + "expr32 " * thirty32s
+ "expr " * (build_count % 32) + "expr " * (collection_size % 32)
+ opname + opname
) )
self.add_unique_rules(["expr ::= %s" % collection, rule], customize) self.add_unique_rules(["expr ::= %s" % collection, rule], customize)
@@ -478,8 +482,8 @@ class Python37BaseParser(PythonParser):
if token.attr == 2: if token.attr == 2:
self.add_unique_rules( self.add_unique_rules(
[ [
"expr ::= build_slice2", "expr ::= slice2",
"build_slice2 ::= expr expr BUILD_SLICE_2", "slice2 ::= expr expr BUILD_SLICE_2",
], ],
customize, customize,
) )
@@ -489,8 +493,8 @@ class Python37BaseParser(PythonParser):
) )
self.add_unique_rules( self.add_unique_rules(
[ [
"expr ::= build_slice3", "expr ::= slice3",
"build_slice3 ::= expr expr expr BUILD_SLICE_3", "slice3 ::= expr expr expr BUILD_SLICE_3",
], ],
customize, customize,
) )
@@ -524,6 +528,7 @@ class Python37BaseParser(PythonParser):
if opname == "CALL_FUNCTION" and token.attr == 1: if opname == "CALL_FUNCTION" and token.attr == 1:
rule = """ rule = """
expr ::= dict_comp
dict_comp ::= LOAD_DICTCOMP LOAD_STR MAKE_FUNCTION_0 expr dict_comp ::= LOAD_DICTCOMP LOAD_STR MAKE_FUNCTION_0 expr
GET_ITER CALL_FUNCTION_1 GET_ITER CALL_FUNCTION_1
classdefdeco1 ::= expr classdefdeco2 CALL_FUNCTION_1 classdefdeco1 ::= expr classdefdeco2 CALL_FUNCTION_1
@@ -558,11 +563,12 @@ class Python37BaseParser(PythonParser):
nak = (len(opname_base) - len("CALL_METHOD")) // 3 nak = (len(opname_base) - len("CALL_METHOD")) // 3
rule = ( rule = (
"call ::= expr " "call ::= expr "
+ ("expr " * args_pos) + ("pos_arg " * args_pos)
+ ("kwarg " * args_kw) + ("kwarg " * args_kw)
+ "expr " * nak + "expr " * nak
+ opname + opname
) )
self.add_unique_rule(rule, opname, token.attr, customize) self.add_unique_rule(rule, opname, token.attr, customize)
elif opname == "CONTINUE": elif opname == "CONTINUE":
@@ -1252,21 +1258,9 @@ class Python37BaseParser(PythonParser):
try: try:
if fn: if fn:
return fn(self, lhs, n, rule, ast, tokens, first, last) return fn(self, lhs, n, rule, ast, tokens, first, last)
except: except Exception:
import sys, traceback import sys, traceback
print(
("Exception in %s %s\n"
+ "rule: %s\n"
+ "offsets %s .. %s")
% (
fn.__name__,
sys.exc_info()[1],
rule2str(rule),
tokens[first].offset,
tokens[last].offset,
)
)
print(traceback.print_tb(sys.exc_info()[2], -1)) print(traceback.print_tb(sys.exc_info()[2], -1))
raise ParserError(tokens[last], tokens[last].off2int(), self.debug["rules"]) raise ParserError(tokens[last], tokens[last].off2int(), self.debug["rules"])

View File

@@ -1,4 +1,4 @@
# Copyright (c) 2016-2021 by Rocky Bernstein # Copyright (c) 2016-2021, 2023 by Rocky Bernstein
# Copyright (c) 2000-2002 by hartmut Goebel <h.goebel@crazy-compilers.com> # Copyright (c) 2000-2002 by hartmut Goebel <h.goebel@crazy-compilers.com>
# Copyright (c) 1999 John Aycock # Copyright (c) 1999 John Aycock
# #
@@ -180,7 +180,7 @@ class Token:
elif name == "LOAD_ASSERT": elif name == "LOAD_ASSERT":
return "%s%s %s" % (prefix, offset_opname, pattr) return "%s%s %s" % (prefix, offset_opname, pattr)
elif self.op in self.opc.NAME_OPS: elif self.op in self.opc.NAME_OPS:
if self.opc.version >= 3.0: if self.opc.version_tuple >= (3, 0):
return "%s%s%s %s" % (prefix, offset_opname, argstr, self.attr) return "%s%s%s %s" % (prefix, offset_opname, argstr, self.attr)
elif name == "EXTENDED_ARG": elif name == "EXTENDED_ARG":
return "%s%s%s 0x%x << %s = %s" % ( return "%s%s%s 0x%x << %s = %s" % (

View File

@@ -170,6 +170,7 @@ def customize_for_version36(self, version):
class_name = node[1][1].attr class_name = node[1][1].attr
if self.is_pypy and class_name.find("<locals>") > 0: if self.is_pypy and class_name.find("<locals>") > 0:
class_name = class_name.split(".")[-1] class_name = class_name.split(".")[-1]
else: else:
class_name = node[1][2].attr class_name = node[1][2].attr
build_class = node build_class = node
@@ -206,23 +207,24 @@ def customize_for_version36(self, version):
elif build_class[1][0] == "load_closure": elif build_class[1][0] == "load_closure":
# Python 3 with closures not functions # Python 3 with closures not functions
load_closure = build_class[1] load_closure = build_class[1]
if hasattr(load_closure[-3], "attr"): subclass_code = None
# Python 3.3 classes with closures work like this. for i in range(-4, -1):
# Note have to test before 3.2 case because if load_closure[i] == "LOAD_CODE":
# index -2 also has an attr. subclass_code = load_closure[i].attr
subclass_code = load_closure[-3].attr break
elif hasattr(load_closure[-2], "attr"): if subclass_code is None:
# Python 3.2 works like this raise RuntimeError(
subclass_code = load_closure[-2].attr "Internal Error n_classdef: cannot find " "class body"
else: )
raise "Internal Error n_classdef: cannot find class body"
if hasattr(build_class[3], "__len__"): if hasattr(build_class[3], "__len__"):
if not subclass_info: if not subclass_info:
subclass_info = build_class[3] subclass_info = build_class[3]
elif hasattr(build_class[2], "__len__"): elif hasattr(build_class[2], "__len__"):
subclass_info = build_class[2] subclass_info = build_class[2]
else: else:
raise "Internal Error n_classdef: cannot superclass name" raise RuntimeError(
"Internal Error n_classdef: cannot " "superclass name"
)
elif node == "classdefdeco2": elif node == "classdefdeco2":
subclass_info = node subclass_info = node
subclass_code = build_class[1][0].attr subclass_code = build_class[1][0].attr

View File

@@ -1,4 +1,4 @@
# Copyright (c) 2019-2022 by Rocky Bernstein # Copyright (c) 2019-2023 by Rocky Bernstein
# #
# This program is free software: you can redistribute it and/or modify # This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by # it under the terms of the GNU General Public License as published by
@@ -16,12 +16,8 @@
""" """
import re import re
from uncompyle6.semantics.consts import (
PRECEDENCE,
TABLE_DIRECT,
INDENT_PER_LEVEL,
)
from uncompyle6.semantics.consts import INDENT_PER_LEVEL, PRECEDENCE, TABLE_DIRECT
from uncompyle6.semantics.helper import flatten_list from uncompyle6.semantics.helper import flatten_list
FSTRING_CONVERSION_MAP = {1: "!s", 2: "!r", 3: "!a", "X": ":X"} FSTRING_CONVERSION_MAP = {1: "!s", 2: "!r", 3: "!a", "X": ":X"}
@@ -54,10 +50,13 @@ def customize_for_version37(self, version):
{ {
"and_not": ("%c and not %c", (0, "expr"), (2, "expr")), "and_not": ("%c and not %c", (0, "expr"), (2, "expr")),
"ann_assign": ( "ann_assign": (
"%|%[2]{attr}: %c\n", 0, "%|%[2]{attr}: %c\n",
0,
), ),
"ann_assign_init": ( "ann_assign_init": (
"%|%[2]{attr}: %c = %c\n", 0, 1, "%|%[2]{attr}: %c = %c\n",
0,
1,
), ),
"async_for_stmt": ( "async_for_stmt": (
"%|async for %c in %c:\n%+%c%-\n\n", "%|async for %c in %c:\n%+%c%-\n\n",
@@ -89,9 +88,8 @@ def customize_for_version37(self, version):
"attributes37": ( "attributes37": (
"%[0]{pattr} import %c", "%[0]{pattr} import %c",
(0, "IMPORT_NAME_ATTR"), (0, "IMPORT_NAME_ATTR"),
(1, "IMPORT_FROM") (1, "IMPORT_FROM"),
), ),
# nested await expressions like: # nested await expressions like:
# return await (await bar()) # return await (await bar())
# need parenthesis. # need parenthesis.
@@ -126,19 +124,24 @@ def customize_for_version37(self, version):
(0, PRECEDENCE["compare"] - 1), (0, PRECEDENCE["compare"] - 1),
(-2, PRECEDENCE["compare"] - 1), (-2, PRECEDENCE["compare"] - 1),
), ),
"compare_chained2a_37": ('%[1]{pattr.replace("-", " ")} %p', (0, PRECEDENCE["compare"] - 1)), "compare_chained2a_37": (
"compare_chained2b_false_37": ('%[1]{pattr.replace("-", " ")} %p', (0, PRECEDENCE["compare"] - 1)), '%[1]{pattr.replace("-", " ")} %p',
"compare_chained2a_false_37": ('%[1]{pattr.replace("-", " ")} %p', (0, PRECEDENCE["compare"] - 1)), (0, PRECEDENCE["compare"] - 1),
),
"compare_chained2b_false_37": (
'%[1]{pattr.replace("-", " ")} %p',
(0, PRECEDENCE["compare"] - 1),
),
"compare_chained2a_false_37": (
'%[1]{pattr.replace("-", " ")} %p',
(0, PRECEDENCE["compare"] - 1),
),
"compare_chained2c_37": ( "compare_chained2c_37": (
'%[3]{pattr.replace("-", " ")} %p %p', '%[3]{pattr.replace("-", " ")} %p %p',
(0, PRECEDENCE["compare"] - 1), (0, PRECEDENCE["compare"] - 1),
(6, PRECEDENCE["compare"] - 1), (6, PRECEDENCE["compare"] - 1),
), ),
'if_exp37': ( "if_exp37": ("%p if %c else %c", (1, "expr", 27), 0, 3),
'%p if %c else %c',
(1, 'expr', 27), 0, 3
),
"except_return": ("%|except:\n%+%c%-", 3), "except_return": ("%|except:\n%+%c%-", 3),
"if_exp_37a": ( "if_exp_37a": (
"%p if %p else %p", "%p if %p else %p",
@@ -153,9 +156,7 @@ def customize_for_version37(self, version):
(5, "expr", 27), (5, "expr", 27),
), ),
"ifstmtl": ("%|if %c:\n%+%c%-", (0, "testexpr"), (1, "_ifstmts_jumpl")), "ifstmtl": ("%|if %c:\n%+%c%-", (0, "testexpr"), (1, "_ifstmts_jumpl")),
'import_as37': ( "import_as37": ("%|import %c as %c\n", 2, -2),
"%|import %c as %c\n", 2, -2
),
"import_from37": ("%|from %[2]{pattr} import %c\n", (3, "importlist37")), "import_from37": ("%|from %[2]{pattr} import %c\n", (3, "importlist37")),
"import_from_as37": ( "import_from_as37": (
"%|from %c as %c\n", "%|from %c as %c\n",
@@ -178,12 +179,11 @@ def customize_for_version37(self, version):
(0, "get_aiter"), (0, "get_aiter"),
(3, "list_iter"), (3, "list_iter"),
), ),
"list_if37": (" if %p%c", (0, 27), 1), "list_if37": (" if %p%c", (0, 27), 1),
"list_if37_not": (" if not %p%c", (0, 27), 1), "list_if37_not": (" if not %p%c", (0, 27), 1),
"testfalse_not_or": ("not %c or %c", (0, "expr"), (2, "expr")), "testfalse_not_or": ("not %c or %c", (0, "expr"), (2, "expr")),
"testfalse_not_and": ("not (%c)", 0), "testfalse_not_and": ("not (%c)", 0),
"testfalsel": ("not %c", (0, "expr")), "testfalsel": ("not %c", (0, "expr")),
"try_except36": ("%|try:\n%+%c%-%c\n\n", 1, -2), "try_except36": ("%|try:\n%+%c%-%c\n\n", 1, -2),
"tryfinally36": ("%|try:\n%+%c%-%|finally:\n%+%c%-\n\n", (1, "returns"), 3), "tryfinally36": ("%|try:\n%+%c%-%|finally:\n%+%c%-\n\n", (1, "returns"), 3),
"dict_unpack": ("{**%C}", (0, -1, ", **")), "dict_unpack": ("{**%C}", (0, -1, ", **")),

View File

@@ -1,4 +1,4 @@
# Copyright (c) 2019-2022 by Rocky Bernstein # Copyright (c) 2019-2023 by Rocky Bernstein
# This program is free software: you can redistribute it and/or modify # This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by # it under the terms of the GNU General Public License as published by
@@ -119,15 +119,10 @@ class TreeTransform(GenericASTTraversal, object):
mkfunc_pattr = node[-1].pattr mkfunc_pattr = node[-1].pattr
if isinstance(mkfunc_pattr, tuple): if isinstance(mkfunc_pattr, tuple):
assert len(mkfunc_pattr, 4) and isinstance(mkfunc_pattr, int) assert len(mkfunc_pattr) == 4 and isinstance(mkfunc_pattr, int)
is_closure = node[-1].pattr[3] != 0
else:
# FIXME: This is what we had before. It is hoaky and probably wrong.
is_closure = mkfunc_pattr == "closure"
if ( if (
(not is_closure) len(code.co_consts) > 0
and len(code.co_consts) > 0
and isinstance(code.co_consts[0], str) and isinstance(code.co_consts[0], str)
): ):
docstring_node = SyntaxTree( docstring_node = SyntaxTree(

View File

@@ -3,7 +3,7 @@
# More could be done here though. # More could be done here though.
from math import copysign from math import copysign
from xdis.version_info import PYTHON_VERSION from xdis.version_info import PYTHON_VERSION_TRIPLE
def is_negative_zero(n): def is_negative_zero(n):
@@ -36,7 +36,7 @@ def better_repr(v, version):
if len(v) == 1: if len(v) == 1:
return "(%s,)" % better_repr(v[0], version) return "(%s,)" % better_repr(v[0], version)
return "(%s)" % ", ".join(better_repr(i, version) for i in v) return "(%s)" % ", ".join(better_repr(i, version) for i in v)
elif PYTHON_VERSION < 3.0 and isinstance(v, long): elif PYTHON_VERSION_TRIPLE < (3, 0) and isinstance(v, long):
s = repr(v) s = repr(v)
if version >= 3.0 and s[-1] == "L": if version >= 3.0 and s[-1] == "L":
return s[:-1] return s[:-1]