-
Notifications
You must be signed in to change notification settings - Fork 55
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Fixes issue 232: Pyani throws an error when it fails to find 3rd-party tool versions (but they are installed) #276
Conversation
I tried just removing the `"-version"` part of the commandline build, as discussed in #232, but then I get an error on MacOS.
Codecov Report
@@ Coverage Diff @@
## master #276 +/- ##
==========================================
+ Coverage 75.66% 75.82% +0.16%
==========================================
Files 52 52
Lines 3291 3338 +47
==========================================
+ Hits 2490 2531 +41
- Misses 801 807 +6 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we should have get_<PROGRAM>_version()
return the "could not retrieve version" string.
Are you going to say the same thing about #218? I get that handling errors at a lower level is potentially desirable, but so is not repeating code if we don't have to (like, if we wanted to handle it differently depending on the tool). I don't know if there may also be more errors we will want to handle at this particular spot in the code, but if we handle them in |
Yes.
More than one approach could make sense here, but here's my reasoning:
and then test specifically for those responses. This is potentially clearer and self-documenting. |
Okay, well, I will still need to catch an error at the lower level. |
The nucmer/BLAST+/legacy BLAST `get_version()` methods now return useful strings for the following events: - no executable at passed path - non-executable file at passed path - no version info returned - version info (path to executable) [intended to mimic library output] The blastall get_version() also catches cases where the blastall executable exists, but is not compiled for the current OS. This is now the case for macOS 11+ with legacy blastall executables
I've added some cases that catch the various types of error we might encounter. Here I've chosen to test for the specific circumstances of the kind of error we might encounter, to aid with diagnostics. This helps when the same class of error (e.g.
Also, there's a new issue since macOS 11 in that the compiled legacy BLAST executable won't run on Big Sur and later. The added code catches I've also modified the "success" string so it has a similar format to that returned for the libraries. See what you think. |
Re an earlier conversation - this is an occasion where squashing commits can be useful. There's no reason to keep cd3997d, 94c71d8, 57e5097 as separate commits. They are conceptually "atomic" - code changes, docstring changes, and a logger message all for the "same thing." As they are consecutive, we can squash these into a single commit which will have a new hash, and will combine the commit messages. See, e.g. https://gitbetter.substack.com/p/how-to-squash-git-commits This can be done with the "squash and merge" option above, though it's not fine-grained and I think it would squash all the commits in the PR. It doesn't change the code, really - just keeps logs tidy and short. |
Looks good. It definitely goes against the "it's better to ask for forgiveness, than permission", Python philosophy, but it's more informative for the user, so it can't be bad. I've gone and added the equivalent code to the |
The EAFP approach is fine a lot of the time, but sometimes there are side effects, and sometimes it contradicts the "explicit is better than implicit" guideline. Here I think it's better to be explicit ("this is what the problem is") than implicit ("there's an attribute error, and one of the several ways in which this could have failed happened"). It's a judgement call. |
Experimenting with mocking to test the new If everything looks good, I would plan on doing the equivalent things for the other subcommands. |
|
Can you share the output (traceback and all) that you get if you try to run Specifically, I'm having trouble getting an OSError to be raised. |
Nevermind! As often happens, immediately after requesting help/insight/what have you, the solution has become apparent. (Or, rather, the reason the solution wasn't quite working has.) New commits to follow shortly. |
Each test case is now its own test. I tried combining them together, but have not found the proper way to do this with monkeypatch.
And make error messages match
And make error messages match
I suspect you'll want some of the things in |
Sadly, no - legacy BLAST is an unmaintained compiled binary and does not run on MacOS 11. |
Fix was using Path object directly, not just the filename (which discards the path information). Could alternatively have built or converted expected list into filenames only. Also turns the list of Path objects into a set for a slight speed up (addresses a TODO comment).
Should avoid any one folder contents scaling with N squared.
Following one user's recent confusion I have combined the first phrase of the Readme with the 'About' description for the repo to make the intended domain clear(er).
The nucmer/BLAST+/legacy BLAST `get_version()` methods now return useful strings for the following events: - no executable at passed path - non-executable file at passed path - no version info returned - version info (path to executable) [intended to mimic library output] The blastall get_version() also catches cases where the blastall executable exists, but is not compiled for the current OS. This is now the case for macOS 11+ with legacy blastall executables
And make error messages match
And make error messages match
I'm restoring the branch for this because I had not yet pulled the more recent changes, and I want to study the tests. |
They should be on |
In writing tests for PR #335, I have begun to question this bit of code: nucmer_path = Path(shutil.which(nucmer_exe)) # type:ignore
if nucmer_path is None:
return f"{nucmer_exe} is not found in $PATH" I don't think Traceback (most recent call last):
File "/Users/baileythegreen/Software/miniconda3/bin/pyani", line 11, in <module>
load_entry_point('pyani', 'console_scripts', 'pyani')()
File "/Users/baileythegreen/Software/pyani/pyani/scripts/pyani_script.py", line 126, in run_main
returnval = args.func(args)
File "/Users/baileythegreen/Software/pyani/pyani/scripts/subcommands/subcmd_listdeps.py", line 86, in subcmd_listdeps
for tool, version in get_tool_versions():
File "/Users/baileythegreen/Software/pyani/pyani/dependencies.py", line 117, in get_tool_versions
yield (name, func())
File "/Users/baileythegreen/Software/pyani/pyani/anim.py", line 113, in get_version
nucmer_path = Path(shutil.which(nucmer_exe)) # type:ignore
File "/Users/baileythegreen/Software/miniconda3/lib/python3.8/pathlib.py", line 1038, in __new__
self = cls._from_parts(args, init=False)
File "/Users/baileythegreen/Software/miniconda3/lib/python3.8/pathlib.py", line 679, in _from_parts
drv, root, parts = self._parse_args(args)
File "/Users/baileythegreen/Software/miniconda3/lib/python3.8/pathlib.py", line 663, in _parse_args
a = os.fspath(a)
TypeError: expected str, bytes or os.PathLike object, not NoneType I propose modifying this to the following: try:
nucmer_path = Path(shutil.which(nucmer_exe)) # type:ignore
# if nucmer_path is None:
except TypeError:
return f"{nucmer_exe} is not found in $PATH" which then allows Installed third-party tool versions...
blast+==Darwin_2.6.0+ (/Users/baileythegreen/Software/miniconda3/bin/blastn)
nucmer==ehfjmoijh is not found in $PATH
blastall==Darwin_2.2.26 (/Users/baileythegreen/Software/miniconda3/bin/blastall) I will incorporate these changes into #335, where I am adding other tests for |
Please include a summary of the change and which issue is fixed. Please also include the motivation and context, and note the tests that apply to these changes.
Fixes #232. A user reported Pyani failing to find a version for
blastall
whenpyani listdeps
was run, butblastall
was installed.It appeared to be caused by OS-dependent differences in the output of the command to obtain
blastall
's version. (User was using Linux.)Just removing the
"-version"
part of the command line then caused the error on MacOS.This PR switches the command line used based on OS, and also gently reports failure to obtain a version number for any third-party tool.
Type of change
Action Checklist
pyani
repository under your own account (please allow write access for repository maintainers)CONTRIBUTING.md
)pytest -v
non-passing code will not be mergedorigin/master
flake8
andblack
before submissionPull requests
section in thepyani
repository