diff options
Diffstat (limited to 'lib')
-rw-r--r-- | lib/spack/spack/audit.py | 40 |
1 files changed, 40 insertions, 0 deletions
diff --git a/lib/spack/spack/audit.py b/lib/spack/spack/audit.py index acc8519a7f..8957320e48 100644 --- a/lib/spack/spack/audit.py +++ b/lib/spack/spack/audit.py @@ -36,6 +36,7 @@ the decorator object, that will forward the keyword arguments passed as input. """ import collections +import inspect import itertools import re @@ -252,6 +253,13 @@ package_directives = AuditClass( kwargs=("pkgs",), ) +package_attributes = AuditClass( + group="packages", + tag="PKG-ATTRIBUTES", + description="Sanity checks on reserved attributes of packages", + kwargs=("pkgs",), +) + #: Sanity checks on linting # This can take some time, so it's run separately from packages @@ -313,6 +321,38 @@ def _check_patch_urls(pkgs, error_cls): return errors +@package_attributes +def _search_for_reserved_attributes_names_in_packages(pkgs, error_cls): + """Ensure that packages don't override reserved names""" + RESERVED_NAMES = ("name",) + errors = [] + for pkg_name in pkgs: + name_definitions = collections.defaultdict(list) + pkg_cls = spack.repo.path.get_pkg_class(pkg_name) + + for cls_item in inspect.getmro(pkg_cls): + for name in RESERVED_NAMES: + current_value = cls_item.__dict__.get(name) + if current_value is None: + continue + name_definitions[name].append((cls_item, current_value)) + + for name in RESERVED_NAMES: + if len(name_definitions[name]) == 1: + continue + + error_msg = ( + "Package '{}' overrides the '{}' attribute or method, " + "which is reserved for Spack internal use" + ) + definitions = [ + "defined in '{}'".format(x[0].__module__) for x in name_definitions[name] + ] + errors.append(error_cls(error_msg.format(pkg_name, name), definitions)) + + return errors + + @package_https_directives def _linting_package_file(pkgs, error_cls): """Check for correctness of links""" |