117 lines
2.9 KiB
Python
117 lines
2.9 KiB
Python
import contextlib
|
|
import functools
|
|
import warnings
|
|
import linecache
|
|
import re
|
|
from collections import OrderedDict
|
|
from collections.abc import Iterable
|
|
from contextlib import contextmanager
|
|
|
|
from .utils import *
|
|
|
|
|
|
__all__ = ["flatten", "union" , "log2_int", "bits_for", "memoize", "final", "deprecated",
|
|
"get_linter_options", "get_linter_option"]
|
|
|
|
|
|
def flatten(i):
|
|
for e in i:
|
|
if isinstance(e, Iterable):
|
|
yield from flatten(e)
|
|
else:
|
|
yield e
|
|
|
|
|
|
def union(i, start=None):
|
|
r = start
|
|
for e in i:
|
|
if r is None:
|
|
r = e
|
|
else:
|
|
r |= e
|
|
return r
|
|
|
|
|
|
def memoize(f):
|
|
memo = OrderedDict()
|
|
@functools.wraps(f)
|
|
def g(*args):
|
|
if args not in memo:
|
|
memo[args] = f(*args)
|
|
return memo[args]
|
|
return g
|
|
|
|
|
|
def final(cls):
|
|
def init_subclass():
|
|
raise TypeError("Subclassing {}.{} is not supported"
|
|
.format(cls.__module__, cls.__name__))
|
|
cls.__init_subclass__ = init_subclass
|
|
return cls
|
|
|
|
|
|
def deprecated(message, stacklevel=2):
|
|
def decorator(f):
|
|
@functools.wraps(f)
|
|
def wrapper(*args, **kwargs):
|
|
warnings.warn(message, DeprecationWarning, stacklevel=stacklevel)
|
|
return f(*args, **kwargs)
|
|
return wrapper
|
|
return decorator
|
|
|
|
|
|
def _ignore_deprecated(f=None):
|
|
if f is None:
|
|
@contextlib.contextmanager
|
|
def context_like():
|
|
with warnings.catch_warnings():
|
|
warnings.filterwarnings(action="ignore", category=DeprecationWarning)
|
|
yield
|
|
return context_like()
|
|
else:
|
|
@functools.wraps(f)
|
|
def decorator_like(*args, **kwargs):
|
|
with warnings.catch_warnings():
|
|
warnings.filterwarnings(action="ignore", category=DeprecationWarning)
|
|
f(*args, **kwargs)
|
|
return decorator_like
|
|
|
|
|
|
def extend(cls):
|
|
def decorator(f):
|
|
if isinstance(f, property):
|
|
name = f.fget.__name__
|
|
else:
|
|
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
|