vendor.lattice_{ecp5,machxo_2_3l}: remove -forceAll from Diamond scripts.
[nmigen.git] / nmigen / _utils.py
1 import contextlib
2 import functools
3 import warnings
4 import linecache
5 import re
6 from collections import OrderedDict
7 from collections.abc import Iterable
8 from contextlib import contextmanager
9
10 from .utils import *
11
12
13 __all__ = ["flatten", "union" , "log2_int", "bits_for", "memoize", "final", "deprecated",
14 "get_linter_options", "get_linter_option"]
15
16
17 def flatten(i):
18 for e in i:
19 if isinstance(e, Iterable):
20 yield from flatten(e)
21 else:
22 yield e
23
24
25 def union(i, start=None):
26 r = start
27 for e in i:
28 if r is None:
29 r = e
30 else:
31 r |= e
32 return r
33
34
35 def memoize(f):
36 memo = OrderedDict()
37 @functools.wraps(f)
38 def g(*args):
39 if args not in memo:
40 memo[args] = f(*args)
41 return memo[args]
42 return g
43
44
45 def final(cls):
46 def init_subclass():
47 raise TypeError("Subclassing {}.{} is not supported"
48 .format(cls.__module__, cls.__name__))
49 cls.__init_subclass__ = init_subclass
50 return cls
51
52
53 def deprecated(message, stacklevel=2):
54 def decorator(f):
55 @functools.wraps(f)
56 def wrapper(*args, **kwargs):
57 warnings.warn(message, DeprecationWarning, stacklevel=stacklevel)
58 return f(*args, **kwargs)
59 return wrapper
60 return decorator
61
62
63 def _ignore_deprecated(f=None):
64 if f is None:
65 @contextlib.contextmanager
66 def context_like():
67 with warnings.catch_warnings():
68 warnings.filterwarnings(action="ignore", category=DeprecationWarning)
69 yield
70 return context_like()
71 else:
72 @functools.wraps(f)
73 def decorator_like(*args, **kwargs):
74 with warnings.catch_warnings():
75 warnings.filterwarnings(action="ignore", category=DeprecationWarning)
76 f(*args, **kwargs)
77 return decorator_like
78
79
80 def extend(cls):
81 def decorator(f):
82 if isinstance(f, property):
83 name = f.fget.__name__
84 else:
85 name = f.__name__
86 setattr(cls, name, f)
87 return decorator
88
89
90 def get_linter_options(filename):
91 first_line = linecache.getline(filename, 1)
92 if first_line:
93 match = re.match(r"^#\s*nmigen:\s*((?:\w+=\w+\s*)(?:,\s*\w+=\w+\s*)*)\n$", first_line)
94 if match:
95 return dict(map(lambda s: s.strip().split("=", 2), match.group(1).split(",")))
96 return dict()
97
98
99 def get_linter_option(filename, name, type, default):
100 options = get_linter_options(filename)
101 if name not in options:
102 return default
103
104 option = options[name]
105 if type is bool:
106 if option in ("1", "yes", "enable"):
107 return True
108 if option in ("0", "no", "disable"):
109 return False
110 return default
111 if type is int:
112 try:
113 return int(option, 0)
114 except ValueError:
115 return default
116 assert False