If a requirement is not satisfied due to an and_dependency or
or_dependency failure, raise a new DependencyError and attach the
original error as its cause (this would be easier if we didn't have to
preserve Python 2.x support). This way we can print the whole chain
(e.g. virtual-shell failed because sh is not installed), instead of
just the lowest level error.
Also indent the messages, because:
check for virtual-editor failed:
or-dependency not satisfied for virtual-editor
For instructions on installing an up-to-date version, see
http://software-carpentry.org/setup/
cause:
check for Notepad++ (notepad++) failed:
could not find 'notepad++' executable
For instructions on installing an up-to-date version, see
http://software-carpentry.org/setup/
is more readable than:
check for virtual-editor failed:
or-dependency not satisfied for virtual-editor
For instructions on installing an up-to-date version, see
http://software-carpentry.org/setup/
cause:
check for Notepad++ (notepad++) failed:
could not find 'notepad++' executable
For instructions on installing an up-to-date version, see
http://software-carpentry.org/setup/
self._message = message
message = property(_get_message, _set_message)
self._message = message
message = property(_get_message, _set_message)
- def __init__(self, checker, message):
+ def __init__(self, checker, message, cause=None):
super(DependencyError, self).__init__(message)
self.checker = checker
self.message = message
super(DependencyError, self).__init__(message)
self.checker = checker
self.message = message
def __str__(self):
url = 'http://software-carpentry.org/setup/' # TODO: per-package URL
def __str__(self):
url = 'http://software-carpentry.org/setup/' # TODO: per-package URL
- return 'check for {0} failed:\n{1}\n{2}\n{3}'.format(
- self.checker.full_name(), self.message,
- 'For instructions on installing an up-to-date version, see',
- url)
+ lines = [
+ 'check for {0} failed:'.format(self.checker.full_name()),
+ ' ' + self.message,
+ ' For instructions on installing an up-to-date version, see',
+ ' ' + url,
+ ]
+ if self.cause:
+ lines.append(' cause:')
+ lines.extend(' ' + line for line in str(self.cause).splitlines())
+ return '\n'.join(lines)
for dependency in self.and_dependencies:
if not hasattr(dependency, 'check'):
dependency = CHECKER[dependency]
for dependency in self.and_dependencies:
if not hasattr(dependency, 'check'):
dependency = CHECKER[dependency]
+ try:
+ dependency.check()
+ except DependencyError as e:
+ raise DependencyError(
+ checker=self,
+ message='and-dependency not satisfied for {0}'.format(
+ self.full_name()),
+ cause=e)
self.or_pass = or_error = None
for dependency in self.or_dependencies:
if not hasattr(dependency, 'check'):
self.or_pass = or_error = None
for dependency in self.or_dependencies:
if not hasattr(dependency, 'check'):
}
break # no need to test other dependencies
if self.or_dependencies and not self.or_pass:
}
break # no need to test other dependencies
if self.or_dependencies and not self.or_pass:
+ raise DependencyError(
+ checker=self,
+ message='or-dependency not satisfied for {0}'.format(
+ self.full_name()),
+ cause=or_error)
def _check(self):
version = self._get_version()
def _check(self):
version = self._get_version()