Skip to content

Commit d2455c8

Browse files
authored
Add logging module to Basilisp (#243)
* Add logging module to Basilisp * Satisfy MyPy overlords * Fix linting errors now
1 parent bdc877f commit d2455c8

File tree

8 files changed

+59
-6
lines changed

8 files changed

+59
-6
lines changed

.prospector.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ pep8:
1616
pylint:
1717
disable:
1818
- len-as-condition
19+
- logging-fstring-interpolation
1920
- no-else-return
2021
- protected-access
2122
- unsubscriptable-object

Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ release:
1313

1414
.PHONY: repl
1515
repl:
16+
@BASILISP_USE_DEV_LOGGER=true
1617
@pipenv run basilisp repl
1718

1819

src/basilisp/cli.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@
1414
import basilisp.main as basilisp
1515
import basilisp.reader as reader
1616

17+
importlib.import_module('basilisp.logging')
18+
1719

1820
@click.group()
1921
def cli():

src/basilisp/compiler.py

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
import functools
55
import importlib
66
import itertools
7+
import logging
78
import sys
89
import types
910
import uuid
@@ -35,6 +36,8 @@
3536
from basilisp.lang.util import genname, munge
3637
from basilisp.util import Maybe, partition
3738

39+
logger = logging.getLogger(__name__)
40+
3841
USE_VAR_INDIRECTION = 'use_var_indirection'
3942

4043
_BUILTINS_NS = 'builtins'
@@ -483,10 +486,8 @@ def _def_ast(ctx: CompilerContext, form: llist.List) -> ASTStream:
483486
yield from meta_nodes
484487
yield from def_nodes
485488

486-
# TODO: log this out, rather than emitting as a warning
487-
# https://github.com/chrisrink10/basilisp/issues/121
488489
if safe_name in ctx.current_ns.module.__dict__:
489-
print(f"WARNING: redefining local Python name '{safe_name}' in module '{ctx.current_ns.module.__name__}'")
490+
logger.warning(f"redefining local Python name '{safe_name}' in module '{ctx.current_ns.module.__name__}'")
490491

491492
yield _dependency(ast.Assign(targets=[ast.Name(id=safe_name, ctx=ast.Store())],
492493
value=Maybe(def_value).map(_unwrap_node).or_else_get(ast.NameConstant(None))))

src/basilisp/importer.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import importlib.machinery
22
import importlib.util
3+
import logging
34
import os.path
45
import sys
56
import types
@@ -11,6 +12,8 @@
1112
import basilisp.reader as reader
1213
from basilisp.lang.util import demunge
1314

15+
logger = logging.getLogger(__name__)
16+
1417

1518
class BasilispImporter(MetaPathFinder, SourceLoader):
1619
"""Python import hook to allow directly loading Basilisp code within
@@ -39,6 +42,7 @@ def find_spec(self,
3942
for filename in filenames:
4043
if os.path.exists(filename):
4144
state = {'fullname': fullname, "filename": filename, 'path': entry, 'target': target}
45+
logger.debug(f"Found potential Basilisp module '{fullname}' in file '{filename}'")
4246
return importlib.machinery.ModuleSpec(fullname, self, origin=filename, loader_state=state)
4347
return None
4448

@@ -59,6 +63,7 @@ def get_filename(self, fullname: str) -> str:
5963
return spec.loader_state.filename
6064

6165
def create_module(self, spec: importlib.machinery.ModuleSpec):
66+
logger.debug(f"Creating Basilisp module '{spec.name}''")
6267
mod = types.ModuleType(spec.name)
6368
mod.__file__ = spec.loader_state["filename"]
6469
mod.__loader__ = spec.loader
@@ -88,8 +93,10 @@ def exec_module(self, module):
8893
ns: runtime.Namespace = runtime.set_current_ns(ns_name).value
8994
ns.module = module
9095

96+
logger.debug(f"Reading and compiling Basilisp module '{fullname}''")
9197
forms = reader.read_file(filename, resolver=runtime.resolve_alias)
9298
compiler.compile_module(forms, compiler.CompilerContext(), module, filename)
99+
logger.debug(f"Loaded Basilisp module '{fullname}''")
93100

94101
# Because we want to (by default) add 'basilisp.core into every namespace by default,
95102
# we want to make sure we don't try to add 'basilisp.core into itself, causing a

src/basilisp/lang/runtime.py

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
import functools
33
import importlib
44
import itertools
5+
import logging
56
import math
67
import threading
78
import types
@@ -23,6 +24,8 @@
2324
from basilisp.lang.typing import LispNumber
2425
from basilisp.util import Maybe
2526

27+
logger = logging.getLogger(__name__)
28+
2629
_CORE_NS = 'basilisp.core'
2730
_REPL_DEFAULT_NS = 'user'
2831
_NS_VAR_NAME = '*ns*'
@@ -741,6 +744,7 @@ def init_ns_var(which_ns: str = _CORE_NS,
741744
core_ns = Namespace.get_or_create(core_sym)
742745
ns_var = Var.intern(
743746
core_sym, sym.Symbol(ns_var_name), core_ns, dynamic=True)
747+
logger.debug(f'Created namespace variable {sym.symbol(ns_var_name, ns=which_ns)}')
744748
return ns_var
745749

746750

@@ -751,9 +755,11 @@ def set_current_ns(ns_name: str,
751755
"""Set the value of the dynamic variable `*ns*` in the current thread."""
752756
symbol = sym.Symbol(ns_name)
753757
ns = Namespace.get_or_create(symbol, module=module)
754-
ns_var = Maybe(Var.find(sym.Symbol(ns_var_name, ns=ns_var_ns))) \
758+
ns_var_sym = sym.Symbol(ns_var_name, ns=ns_var_ns)
759+
ns_var = Maybe(Var.find(ns_var_sym)) \
755760
.or_else_raise(lambda: RuntimeException(f"Dynamic Var {sym.Symbol(ns_var_name, ns=ns_var_ns)} not bound!"))
756761
ns_var.push_bindings(ns)
762+
logger.debug(f'Setting {ns_var_sym} to {ns}')
757763
return ns_var
758764

759765

@@ -765,27 +771,32 @@ def ns_bindings(ns_name: str,
765771
"""Context manager for temporarily changing the value of basilisp.core/*ns*."""
766772
symbol = sym.Symbol(ns_name)
767773
ns = Namespace.get_or_create(symbol, module=module)
768-
ns_var = Maybe(Var.find(sym.Symbol(ns_var_name, ns=ns_var_ns))) \
774+
ns_var_sym = sym.Symbol(ns_var_name, ns=ns_var_ns)
775+
ns_var = Maybe(Var.find(ns_var_sym)) \
769776
.or_else_raise(lambda: RuntimeException(f"Dynamic Var {sym.Symbol(ns_var_name, ns=ns_var_ns)} not bound!"))
770777

771778
try:
779+
logger.debug(f'Binding {ns_var_sym} to {ns}')
772780
ns_var.push_bindings(ns)
773781
yield ns_var.value
774782
finally:
775783
ns_var.pop_bindings()
784+
logger.debug(f'Reset bindings for {ns_var_sym} to {ns_var.value}')
776785

777786

778787
@contextlib.contextmanager
779788
def remove_ns_bindings(ns_var_name: str = _NS_VAR_NAME,
780789
ns_var_ns: str = _NS_VAR_NS):
781790
"""Context manager to pop the most recent bindings for basilisp.core/*ns* after
782791
completion of the code under management."""
783-
ns_var = Maybe(Var.find(sym.Symbol(ns_var_name, ns=ns_var_ns))) \
792+
ns_var_sym = sym.Symbol(ns_var_name, ns=ns_var_ns)
793+
ns_var = Maybe(Var.find(ns_var_sym)) \
784794
.or_else_raise(lambda: RuntimeException(f"Dynamic Var {sym.Symbol(ns_var_name, ns=ns_var_ns)} not bound!"))
785795
try:
786796
yield
787797
finally:
788798
ns_var.pop_bindings()
799+
logger.debug(f'Reset bindings for {ns_var_sym} to {ns_var.value}')
789800

790801

791802
def get_current_ns(ns_var_name: str = _NS_VAR_NAME,

src/basilisp/logging.py

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
import logging
2+
import os
3+
4+
5+
def _get_default_level() -> str:
6+
"""Get the default logging level for Basilisp."""
7+
return os.getenv('BASILISP_LOGGING_LEVEL', 'WARNING')
8+
9+
10+
def _get_default_handler(level: str, formatter: logging.Formatter) -> logging.Handler:
11+
"""Get the default logging handler for Basilisp."""
12+
handler: logging.Handler = logging.NullHandler()
13+
if os.getenv('BASILISP_USE_DEV_LOGGER') == 'true':
14+
handler = logging.StreamHandler()
15+
16+
handler.setFormatter(formatter)
17+
handler.setLevel(level)
18+
return handler
19+
20+
21+
_DEFAULT_FORMAT = '%(asctime)s %(levelname)s [%(name)s.%(funcName)s:%(lineno)d] - %(message)s'
22+
_DEFAULT_FORMATTER = logging.Formatter(_DEFAULT_FORMAT)
23+
_DEFAULT_LEVEL = _get_default_level()
24+
_DEFAULT_HANDLER = _get_default_handler(_DEFAULT_LEVEL, _DEFAULT_FORMATTER)
25+
26+
logger = logging.getLogger('basilisp')
27+
logger.setLevel(_DEFAULT_LEVEL)
28+
logger.addHandler(_DEFAULT_HANDLER)

src/basilisp/main.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33
import basilisp.importer as importer
44
import basilisp.lang.runtime as runtime
55

6+
importlib.import_module('basilisp.logging')
7+
68

79
def init():
810
"""Initialize the runtime environment for evaluation."""

0 commit comments

Comments
 (0)