check_support; Attribute()

This commit is contained in:
Yuyao Huang 2024-04-22 16:43:21 +08:00
parent 0281d68cb4
commit c620d0b014
11 changed files with 74 additions and 9 deletions

View File

@ -1,9 +1,10 @@
from tests.test_utils import *
from trace_commentor.check import Check
def test():
@Commentor()
# @Commentor()
@Check()
def target(a, d=1, *b, c, k=1):
return a + k

View File

@ -13,6 +13,7 @@ def test_constant():
x = 2
print(x == 2)
"""
<callable> : print
True : x == 2
None : print(x == 2)
"""
@ -64,7 +65,7 @@ def test_if():
def test_for():
with closing(StringIO()) as f:
@Commentor(f)
@Commentor(f, _exit=False, check=False)
def target():
odds = []
# return only odd numbers - 1,3,5,7,9
@ -101,6 +102,8 @@ def test_for():
# continue # skipped
# odds.append(x)
"""
[] : odds
<callable> : odds.append
1 : x
None : odds.append(x)
"""
@ -125,6 +128,8 @@ def test_for():
# continue # skipped
# odds.append(x)
"""
[1] : odds
<callable> : odds.append
3 : x
None : odds.append(x)
"""
@ -149,6 +154,8 @@ def test_for():
# continue # skipped
# odds.append(x)
"""
[1, 3] : odds
<callable> : odds.append
5 : x
None : odds.append(x)
"""
@ -173,6 +180,8 @@ def test_for():
# continue # skipped
# odds.append(x)
"""
[1, 3, 5] : odds
<callable> : odds.append
7 : x
None : odds.append(x)
"""
@ -197,6 +206,8 @@ def test_for():
continue # skipped
odds.append(x)
"""
[1, 3, 5, 7] : odds
<callable> : odds.append
9 : x
None : odds.append(x)
"""

View File

@ -17,7 +17,7 @@ def test_return():
with closing(StringIO()) as f:
@Commentor(f)
@Commentor(f, _exit=False)
def target():
a = 1
return a + 1

View File

@ -46,6 +46,7 @@ def test_call_print():
def target():
print('This line will be printed.')
"""
<callable> : print
None : print('This line will be printed.')
"""
''')

View File

@ -14,6 +14,7 @@ def test_assign():
myint = 7
print(myint)
"""
<callable> : print
7 : myint
None : print(myint)
"""

View File

@ -9,12 +9,12 @@ from functools import wraps
from . import handlers
from . import formatters
from . import flags
from .utils import sign, to_source, comment_to_file
from .utils import sign, to_source, comment_to_file, isinstance_noexcept
class Commentor(object):
def __init__(self, output="<stderr>", _globals=dict(), fmt=[]) -> None:
def __init__(self, output="<stderr>", _globals=dict(), fmt=[], check=True, _exit=True) -> None:
self._locals = dict()
self._globals = dict().update(_globals)
self._return = None
@ -25,6 +25,8 @@ class Commentor(object):
self.state = flags.SOURCE
self.file = output
self._stack_event = flags.NORMAL
self._exit = _exit
self._check = check
def __call__(self, func):
@ -32,6 +34,8 @@ class Commentor(object):
self.indent = len(raw_lines[0]) - len(raw_lines[0].lstrip())
unindented_source = ''.join([l[self.indent:] for l in raw_lines])
self.root = ast.parse(unindented_source).body[0]
if self._check: self.check_support()
pt = getfullargspec(func)
if flags.DEBUG:
@ -71,6 +75,8 @@ class Commentor(object):
# output {
comments = "\n".join(self._lines)
if comment_to_file(comments, file=self.file):
if self._exit:
exit(0)
return self._return
else:
return comments
@ -102,7 +108,9 @@ class Commentor(object):
def get_formatter(self, obj):
for typ, fmt in self._formatters:
if isinstance(obj, typ):
if isinstance_noexcept(obj, typ):
return fmt
elif callable(typ) and typ(obj):
return fmt
else:
return repr
@ -128,3 +136,17 @@ class Commentor(object):
self.__append('"""')
if line is not None:
return self.__append(sign(line, 2))
def check_support(self):
unimpl = []
for node in ast.walk(self.root):
if node.__class__ in flags.HANDLER_FREE_NODES:
continue
node_type = node.__class__.__name__
handler = getattr(handlers, node_type, None)
if handler is None:
unimpl.append(node_type)
if unimpl:
print("Unsupported nodes: ", ", ".join(unimpl))
exit(0)

View File

@ -21,3 +21,10 @@ APPEND_SOURCE_BY_THEMSELVES = [
ASSIGN_SILENT = [
ast.Constant, ast.List
]
HANDLER_FREE_NODES = [
ast.Add, ast.Sub, ast.Mult, ast.Div, ast.FloorDiv, ast.Mod, ast.LShift, ast.RShift, ast.BitOr, ast.BitXor, ast.BitAnd, ast.MatMult,
ast.Eq, ast.NotEq, ast.Lt, ast.LtE, ast.Gt, ast.GtE, ast.Is, ast.IsNot, ast.In, ast.NotIn,
ast.Load, ast.Store,
ast.arg, ast.arguments, ast.keyword,
]

View File

@ -1 +1,7 @@
LIST = []
def fmt_callable(fn):
return "<callable>"
LIST = [
(callable, fmt_callable),
]

View File

@ -1,6 +1,6 @@
from .definitions import FunctionDef, Return
from .statements import Pass, Assign
from .expressions import Expr, BinOp, Call, Compare
from .expressions import Expr, BinOp, Call, Compare, Attribute
from .literals import Constant, Tuple, List
from .variables import Name
from .control_flow import If, For, Continue, Break

View File

@ -12,8 +12,13 @@ def Compare(self, cmtor):
cmtor.append_comment(cmtor.eval(self))
def Call(self, cmtor):
cmtor.process(self.func)
for arg in self.args:
cmtor.process(arg)
for kwarg in self.keywords:
cmtor.process(kwarg)
cmtor.append_comment(cmtor.eval(self))
def Attribute(self, cmtor):
cmtor.process(self.value)
cmtor.append_comment(cmtor.eval(self))

View File

@ -26,6 +26,10 @@ def to_source(node):
return src
def dump(node, file=sys.stderr):
print(ast.dump(node, indent=4), file=file)
def comment_to_file(code, file: str) -> bool:
if file == "<return>":
return False
@ -49,3 +53,10 @@ def comment_to_file(code, file: str) -> bool:
else:
raise NotImplementedError(f"Unknown file protocal {file}")
return True
def isinstance_noexcept(_obj, _class_or_tuple):
try:
return isinstance(_obj, _class_or_tuple)
except TypeError:
return False