|
1 | 1 | from importlib import import_module |
2 | 2 | from inspect import getmembers, isfunction |
| 3 | +from pkgutil import walk_packages |
3 | 4 | from typing import Any, Callable, Dict, Iterable, Optional, List, Union |
4 | 5 |
|
5 | 6 | from eth2spec.utils import bls |
@@ -134,3 +135,69 @@ def combine_mods(dict_1, dict_2): |
134 | 135 | dict_3[key].append(dict_1[key]) |
135 | 136 |
|
136 | 137 | return dict_3 |
| 138 | + |
| 139 | + |
| 140 | +def check_mods(all_mods, pkg): |
| 141 | + """ |
| 142 | + Raise an exception if there is a missing/unexpected module in all_mods. |
| 143 | + """ |
| 144 | + def get_expected_modules(package, absolute=False): |
| 145 | + """ |
| 146 | + Return all modules (which are not packages) inside the given package. |
| 147 | + """ |
| 148 | + modules = [] |
| 149 | + eth2spec = import_module('eth2spec') |
| 150 | + prefix = eth2spec.__name__ + '.' |
| 151 | + for _, modname, ispkg in walk_packages(eth2spec.__path__, prefix): |
| 152 | + s = package if absolute else f'.{package}.' |
| 153 | + if s in modname and not ispkg: |
| 154 | + modules.append(modname) |
| 155 | + return modules |
| 156 | + |
| 157 | + mods = [] |
| 158 | + for fork in all_mods: |
| 159 | + for mod in all_mods[fork].values(): |
| 160 | + # If this key has a single value, normalize to list. |
| 161 | + if isinstance(mod, str): |
| 162 | + mod = [mod] |
| 163 | + |
| 164 | + # For each submodule, check if it is package. |
| 165 | + # This is a "trick" we do to reuse a test format. |
| 166 | + for sub in mod: |
| 167 | + is_package = '.test_' not in sub |
| 168 | + if is_package: |
| 169 | + mods.extend(get_expected_modules(sub, absolute=True)) |
| 170 | + else: |
| 171 | + mods.append(sub) |
| 172 | + |
| 173 | + problems = [] |
| 174 | + expected_mods = get_expected_modules(pkg) |
| 175 | + if mods != expected_mods: |
| 176 | + for e in expected_mods: |
| 177 | + # Skip forks which are not in all_mods. |
| 178 | + # The fork name is the 3rd item in the path. |
| 179 | + fork = e.split('.')[2] |
| 180 | + if fork not in all_mods: |
| 181 | + continue |
| 182 | + # Skip modules in the unittests package. |
| 183 | + # These are not associated with generators. |
| 184 | + if '.unittests.' in e: |
| 185 | + continue |
| 186 | + # The expected module is not in our list of modules. |
| 187 | + # Add it to our list of problems. |
| 188 | + if e not in mods: |
| 189 | + problems.append('missing: ' + e) |
| 190 | + |
| 191 | + for t in mods: |
| 192 | + # Skip helper modules. |
| 193 | + # These do not define test functions. |
| 194 | + if t.startswith('eth2spec.test.helpers'): |
| 195 | + continue |
| 196 | + # There is a module not defined in eth2spec. |
| 197 | + # Add it to our list of problems. |
| 198 | + if t not in expected_mods: |
| 199 | + print('unexpected:', t) |
| 200 | + problems.append('unexpected: ' + t) |
| 201 | + |
| 202 | + if problems: |
| 203 | + raise Exception('[ERROR] module problems:\n ' + '\n '.join(problems)) |
0 commit comments