First implementation of Debugger for SyaNodeParser

This commit is contained in:
2020-12-03 21:50:48 +01:00
parent 4f899280c4
commit 8b86998225
48 changed files with 1781 additions and 1795 deletions
+88 -49
View File
@@ -1,16 +1,15 @@
import ast
import importlib
import inspect
import os
import pkgutil
from copy import deepcopy
from cache.Cache import Cache
from core.ast_helpers import ast_to_props
from core.tokenizer import TokenKind, Tokenizer
from pyparsing import *
default_debug_name = "*default*"
debug_activated = set()
COLORS = {
"black",
"red",
@@ -43,55 +42,17 @@ integer = Word(nums)
escapeSeq = Combine(ESC + '[' + Optional(delimitedList(integer, ';')) +
oneOf(list(alphas)))
try:
CONSOLE_ROWS, CONSOLE_COLUMNS = os.popen('stty size', 'r').read().split()
CONSOLE_ROWS, CONSOLE_COLUMNS = int(CONSOLE_ROWS), int(CONSOLE_COLUMNS)
except ValueError:
CONSOLE_ROWS, CONSOLE_COLUMNS = 50, 80
def no_color_str(text):
return Suppress(escapeSeq).transformString(str(text))
def my_debug(*args, check_started=None):
"""
Write one line per arg in 'debug.txt'
:param args:
:param check_started:
True : first check if start_debug() was called
<name> : first check if start_debug(name) was called
list of <names> : first check if start_debug() is called for all names
:return:
"""
if check_started and default_debug_name not in debug_activated:
return
if isinstance(check_started, str) and check_started not in debug_activated:
return
if isinstance(check_started, list):
for debug_name in check_started:
if debug_name not in debug_activated:
return
with open("debug.txt", "a") as f:
for arg in args:
if isinstance(arg, list):
for item in arg:
f.write(f"{item}\n")
else:
f.write(f"{arg}\n")
def start_debug(debug_name=default_debug_name, msg=None):
debug_activated.add(debug_name)
if msg:
with open("debug.txt", "a") as f:
f.write(f"{msg}\n")
def stop_debug(debug_name=default_debug_name, msg=None):
if msg:
with open("debug.txt", "a") as f:
f.write(f"{msg}\n")
debug_activated.remove(debug_name)
def sysarg_to_string(argv):
"""
Transform a list of strings into a single string
@@ -606,13 +567,17 @@ def tokens_index(tokens, sub_tokens, skip=0):
raise ValueError(f"sub tokens '{sub_tokens}' not found")
def as_bag(obj):
def as_bag(obj, forced_properties=None):
"""
Get the properties of an object (static and dynamic)
:param obj:
:param forced_properties:
:return:
"""
if hasattr(obj, "as_bag"):
if forced_properties:
bag = {p: getattr(obj, p) for p in forced_properties}
elif hasattr(obj, "as_bag"):
bag = obj.as_bag()
else:
bag = {} if type(obj) in PRIMITIVES_TYPES else {prop: getattr(obj, prop)
@@ -726,3 +691,77 @@ def dump_ast(node):
for to_remove in [", ctx=Load()", ", kind=None", ", type_ignores=[]"]:
dump = dump.replace(to_remove, "")
return dump
def sheerka_deepcopy(obj):
"""
Internal implementation of deepcopy that can handle Concept circular references
:param obj:
:return:
"""
already_seen = {}
def copy_concept(c):
id_c = id(c)
if id_c in already_seen:
ref = already_seen[id_c]
if ref == '_##_REF_##_':
raise Exception("Circular Ref not managed yet!")
else:
return ref
already_seen[id_c] = '_##_REF_##_'
cls = type(c)
instance = cls()
# update the metadata
for prop_name, prop_value in vars(c.get_metadata()).items():
if prop_name != "props":
setattr(instance.get_metadata(), prop_name, prop_value)
else:
setattr(instance.get_metadata(), prop_name, sheerka_deepcopy(prop_value))
# update the values
for prop_name, prop_value in c.values().items():
setattr(instance, prop_name, prop_value)
already_seen[id_c] = instance
return instance
from core.concept import Concept
if isinstance(obj, dict):
res = {sheerka_deepcopy(k): sheerka_deepcopy(v) for k, v in obj.items()}
return res
elif isinstance(obj, list):
return [sheerka_deepcopy(item) for item in obj]
elif isinstance(obj, set):
return {sheerka_deepcopy(item) for item in obj}
elif isinstance(obj, tuple):
return tuple((sheerka_deepcopy(item) for item in obj))
elif isinstance(obj, Concept):
return copy_concept(obj)
else:
return deepcopy(obj)
def escape_str(x):
"""
Returns a string representation that look like what would produce a debugger
:param x:
:return:
"""
if isinstance(x, str):
return f"'{x}'"
return x
class NextIdManager:
"""
solely return the next integer
"""
def __init__(self):
self.id = -1
def get_next_id(self):
self.id += 1
return self.id