From 0ef572500e17f0f1456b180e01902bff5b870a7e Mon Sep 17 00:00:00 2001 From: crosenblatt Date: Fri, 5 Jun 2020 18:10:47 -0400 Subject: [PATCH] Add logging Initial addition of logging to cl4py. Subject to modification as the need arises. --- cl4py/data.py | 8 ++++++++ cl4py/lisp.py | 39 +++++++++++++++++++++++++++++++++------ cl4py/reader.py | 15 ++++++++++++++- cl4py/writer.py | 4 ++++ 4 files changed, 59 insertions(+), 7 deletions(-) diff --git a/cl4py/data.py b/cl4py/data.py index b8d87ac..94fe118 100644 --- a/cl4py/data.py +++ b/cl4py/data.py @@ -23,6 +23,9 @@ ''' import reprlib +import logging + +logging.basicConfig(level=logging.DEBUG) class LispObject: pass @@ -96,10 +99,13 @@ def __eq__(self, other): def python_name(self): name = self.name if name in python_name_translations: + logging.info("Translated lisp {} to python {}".format(name, python_name_translations[name])) return python_name_translations[name] else: + old_name = name for (old, new) in python_name_substitutions.items(): name = name.replace(old, new) + logging.info("Translated lisp {} to python {}".format(old_name, name)) return name.lower() @@ -118,6 +124,7 @@ def __getitem__(self, name): class Cons (LispObject): def __init__(self, car, cdr): + logging.info("Created new cons {} {}".format(car, cdr)) self.car = car self.cdr = cdr @@ -241,6 +248,7 @@ def __del__(self): def __call__(self, *args, **kwargs): restAndKeys = [ Quote(arg) for arg in args ] + logging.info("restAndKeys: {}".format(restAndKeys)) for key, value in kwargs.items(): restAndKeys.append(Keyword(key.upper())) restAndKeys.append(Quote(value)) diff --git a/cl4py/lisp.py b/cl4py/lisp.py index b0857ff..dc822d5 100644 --- a/cl4py/lisp.py +++ b/cl4py/lisp.py @@ -7,10 +7,12 @@ from .data import * from .reader import Readtable from .writer import lispify +import logging +import sys - +logging.basicConfig(level=logging.DEBUG) class Lisp: - def __init__(self, cmd=['sbcl', '--script'], quicklisp=False): + def __init__(self, cmd=['sbcl', '--script'], quicklisp=False, debug=False): p = subprocess.Popen(cmd + [resource_filename(__name__, 'py.lisp')], stdin = subprocess.PIPE, stdout = subprocess.PIPE, @@ -31,17 +33,24 @@ def __init__(self, cmd=['sbcl', '--script'], quicklisp=False): # This allows us to patch these instances later. self.unpatched_instances = {} # If debug is true, cl4py will print plenty of debug information. - self.debug = False + self.debug = debug # Finally, check whether the user wants quicklisp to be available. + logging.info("Created new Lisp instance:\ncmd: {}\nquicklisp: {}\ndebug: {}".format(cmd, quicklisp, debug)) if quicklisp: + logging.info("Installing QuickLisp...") install_and_load_quicklisp(self) + logging.info("QuickLisp installed.") def __del__(self): try: + logging.info("Deleting instance...") self.stdin.write('(cl-user:quit)\n') + logging.info("Instance deleted") except: - pass + logging.debug("Instance deletion failed.") + logging.debug(sys.exc_info()[0]) + # pass def eval(self, expr): @@ -60,6 +69,7 @@ def eval(self, expr): if isinstance(err, Cons): condition = err.car msg = err.cdr.car if err.cdr else "" + logging.debug("Error being raised in lisp.py/eval.\nerr = {}\ncondition = {}\nmsg = {}".format(err, condition, msg)) def init(self): RuntimeError.__init__(self, msg) raise type(str(condition), (RuntimeError,), @@ -72,38 +82,54 @@ def init(self): cls = type(cls_name.python_name, (LispWrapper,), {}) self.classes[cls_name] = cls alist = self.function('cl4py:class-information')(cls_name) + logging.info("Adding member functions for {}".format(cls_name)) for cons in alist: add_member_function(cls, cons.car, cons.cdr) for instance in instances: + logging.info("Patching {} with class {}".format(instance, cls_name)) instance.__class__ = cls # Finally, return the resulting values. if val == (): + logging.info("{} returns None".format(expr)) return None elif val.cdr == (): + logging.info("{} returns {}".format(expr, val.car)) return val.car else: - return tuple(val) + ret = tuple(val) + logging.info("{} returns {}".format(expr, ret)) + return ret def find_package(self, name): + logging.info("Finding package {}".format(name)) return self.function('CL:FIND-PACKAGE')(name) + # logging.info("Package {} Found: {}".format(name, p)) + # return p def function(self, name): - return self.eval( ('CL:FUNCTION', name) ) + logging.info("Evaluating {}".format(name)) + e = self.eval( ('CL:FUNCTION', name) ) + logging.info("Evaluated {} Found {}".format(name, e)) + return e def add_member_function(cls, name, gf): class_name = cls.__name__ method_name = name.python_name + logging.info("Adding member function. Method {}, Class {}".format(method_name, class_name)) setattr(cls, method_name, lambda self, *args: gf(self, *args)) def install_and_load_quicklisp(lisp): + logging.info("Installing QuickLisp") quicklisp_setup = os.path.expanduser('~/quicklisp/setup.lisp') if os.path.isfile(quicklisp_setup): lisp.function('cl:load')(quicklisp_setup) + logging.info("QuickLisp found already and loaded.") else: + logging.info("Installing from outside.") install_quicklisp(lisp) @@ -116,3 +142,4 @@ def install_quicklisp(lisp): lisp.function('cl:load')(tmp.name) print('Installing Quicklisp...') lisp.eval( ('quicklisp-quickstart:install',) ) + logging.info("QuickLisp installed from outside.") diff --git a/cl4py/reader.py b/cl4py/reader.py index 203cb7a..f863d71 100644 --- a/cl4py/reader.py +++ b/cl4py/reader.py @@ -8,6 +8,8 @@ from .data import * from .circularity import * +logging.basicConfig(level=logging.DEBUG) + # An implementation of the Common Lisp reader algorithm, with the following # simplifications and changes: # @@ -160,17 +162,21 @@ def read_aux(self, stream): def parse(self, token): + logging.info("Parsing: {}".format(token)) # integer m = re.fullmatch(integer_regex, token) if m: + logging.info("Parsed {} as integer".format(token)) return int(m.group(0)) # ratio m = re.fullmatch(ratio_regex, token) if m: + logging.info("Parsed {} as ratio".format(token)) return Fraction(int(m.group(1)), int(m.group(2))) # float m = re.fullmatch(float_regex, token) if m: + logging.info("Parsed {} as float".format(token)) base = m.group(1) exponent_marker = m.group(2) exponent = m.group(3) @@ -187,6 +193,7 @@ def parse(self, token): # symbol m = re.fullmatch(symbol_regex, token) if m: + logging.info("Parsed {} as symbol".format(token)) package = m.group(1) delimiter = m.group(2) name = m.group(3) @@ -229,7 +236,10 @@ def skip_whitespace(): def left_parenthesis(r, s, c): - return r.read_delimited_list(')', s, True) + logging.info("Left parenthesis found, reading delimited list") + l = r.read_delimited_list(')', s, True) + logging.info("List read: {}".format(r)) + return l def right_parenthesis(r, s, c): @@ -237,6 +247,7 @@ def right_parenthesis(r, s, c): def left_curly_bracket(r, s, c): + logging.info("Left curly bracket found, reading delimited list") table = {} data = r.read_delimited_list('}', s, True) while data: @@ -247,6 +258,7 @@ def left_curly_bracket(r, s, c): value = car(rest) table[key] = value data = cdr(rest) + logging.info("Table read: {}".format(table)) return table @@ -314,6 +326,7 @@ def sharpsign_backslash(r, s, c, n): else: key = ''.join(token).upper() if key in character_names: + logging.info("Reading special character {}".format(key)) return character_names[key] else: raise RuntimeError('Not a valid character name: {}'.format('key')) diff --git a/cl4py/writer.py b/cl4py/writer.py index e27be5b..0424a45 100644 --- a/cl4py/writer.py +++ b/cl4py/writer.py @@ -5,6 +5,9 @@ from fractions import Fraction from .data import * from .circularity import * +import logging + +logging.basicConfig(level=logging.DEBUG) def lispify(lisp, obj): return lispify_datum(decircularize(obj, lisp.readtable)) @@ -12,6 +15,7 @@ def lispify(lisp, obj): def lispify_datum(obj): lispifier = lispifiers.get(type(obj)) + logging.info("obj {} is type {}".format(obj, lispifier)) if lispifier: return lispifier(obj) elif isinstance(obj, LispWrapper):