diff --git a/nmigen/_utils.py b/nmigen/_utils.py index 85c8cdb..6168ea1 100644 --- a/nmigen/_utils.py +++ b/nmigen/_utils.py @@ -1,6 +1,8 @@ import contextlib import functools import warnings +import linecache +import re from collections import OrderedDict from collections.abc import Iterable from contextlib import contextmanager @@ -8,7 +10,8 @@ from contextlib import contextmanager from .utils import * -__all__ = ["flatten", "union" , "log2_int", "bits_for", "memoize", "final", "deprecated"] +__all__ = ["flatten", "union" , "log2_int", "bits_for", "memoize", "final", "deprecated", + "get_linter_options", "get_linter_option"] def flatten(i): @@ -82,3 +85,32 @@ def extend(cls): name = f.__name__ setattr(cls, name, f) return decorator + + +def get_linter_options(filename): + first_line = linecache.getline(filename, 1) + if first_line: + match = re.match(r"^#\s*nmigen:\s*((?:\w+=\w+\s*)(?:,\s*\w+=\w+\s*)*)\n$", first_line) + if match: + return dict(map(lambda s: s.strip().split("=", 2), match.group(1).split(","))) + return dict() + + +def get_linter_option(filename, name, type, default): + options = get_linter_options(filename) + if name not in options: + return default + + option = options[name] + if type is bool: + if option in ("1", "yes", "enable"): + return True + if option in ("0", "no", "disable"): + return False + return default + if type is int: + try: + return int(option, 0) + except ValueError: + return default + assert False diff --git a/nmigen/hdl/ir.py b/nmigen/hdl/ir.py index 44c3ecd..c213943 100644 --- a/nmigen/hdl/ir.py +++ b/nmigen/hdl/ir.py @@ -21,19 +21,24 @@ class Elaboratable(metaclass=ABCMeta): _Elaboratable__silence = False def __new__(cls, *args, src_loc_at=0, **kwargs): + frame = sys._getframe(1 + src_loc_at) self = super().__new__(cls) - self._Elaboratable__src_loc = traceback.extract_stack(limit=2 + src_loc_at)[0] self._Elaboratable__used = False + self._Elaboratable__context = dict( + filename=frame.f_code.co_filename, + lineno=frame.f_lineno, + source=self) return self def __del__(self): if self._Elaboratable__silence: return if hasattr(self, "_Elaboratable__used") and not self._Elaboratable__used: - warnings.warn_explicit("{!r} created but never used".format(self), UnusedElaboratable, - filename=self._Elaboratable__src_loc.filename, - lineno=self._Elaboratable__src_loc.lineno, - source=self) + if get_linter_option(self._Elaboratable__context["filename"], + "UnusedElaboratable", bool, True): + warnings.warn_explicit( + "{!r} created but never used".format(self), UnusedElaboratable, + **self._Elaboratable__context) _old_excepthook = sys.excepthook