diff options
Diffstat (limited to 'Lib/packaging/command/check.py')
-rw-r--r-- | Lib/packaging/command/check.py | 88 |
1 files changed, 88 insertions, 0 deletions
diff --git a/Lib/packaging/command/check.py b/Lib/packaging/command/check.py new file mode 100644 index 0000000..6715db9 --- /dev/null +++ b/Lib/packaging/command/check.py @@ -0,0 +1,88 @@ +"""Check PEP compliance of metadata.""" + +from packaging import logger +from packaging.command.cmd import Command +from packaging.errors import PackagingSetupError +from packaging.util import resolve_name + +class check(Command): + + description = "check PEP compliance of metadata" + + user_options = [('metadata', 'm', 'Verify metadata'), + ('all', 'a', + ('runs extended set of checks')), + ('strict', 's', + 'Will exit with an error if a check fails')] + + boolean_options = ['metadata', 'all', 'strict'] + + def initialize_options(self): + """Sets default values for options.""" + self.all = False + self.metadata = True + self.strict = False + self._warnings = [] + + def finalize_options(self): + pass + + def warn(self, msg, *args): + """Wrapper around logging that also remembers messages.""" + # XXX we could use a special handler for this, but would need to test + # if it works even if the logger has a too high level + self._warnings.append((msg, args)) + return logger.warning('%s: %s' % (self.get_command_name(), msg), *args) + + def run(self): + """Runs the command.""" + # perform the various tests + if self.metadata: + self.check_metadata() + if self.all: + self.check_restructuredtext() + self.check_hooks_resolvable() + + # let's raise an error in strict mode, if we have at least + # one warning + if self.strict and len(self._warnings) > 0: + msg = '\n'.join(msg % args for msg, args in self._warnings) + raise PackagingSetupError(msg) + + def check_metadata(self): + """Ensures that all required elements of metadata are supplied. + + name, version, URL, author + + Warns if any are missing. + """ + missing, warnings = self.distribution.metadata.check(strict=True) + if missing != []: + self.warn('missing required metadata: %s', ', '.join(missing)) + for warning in warnings: + self.warn(warning) + + def check_restructuredtext(self): + """Checks if the long string fields are reST-compliant.""" + missing, warnings = self.distribution.metadata.check(restructuredtext=True) + if self.distribution.metadata.docutils_support: + for warning in warnings: + line = warning[-1].get('line') + if line is None: + warning = warning[1] + else: + warning = '%s (line %s)' % (warning[1], line) + self.warn(warning) + elif self.strict: + raise PackagingSetupError('The docutils package is needed.') + + def check_hooks_resolvable(self): + for options in self.distribution.command_options.values(): + for hook_kind in ("pre_hook", "post_hook"): + if hook_kind not in options: + break + for hook_name in options[hook_kind][1].values(): + try: + resolve_name(hook_name) + except ImportError: + self.warn('name %r cannot be resolved', hook_name) |