Skip to content
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

add tests for missing libraries #127

Merged
merged 15 commits into from
Feb 28, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/coverage.yml
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ jobs:
path: coverage.xml
repo_token: ${{ secrets.GITHUB_TOKEN }}
pull_request_number: ${{ steps.get-pr.outputs.PR }}
minimum_coverage: 75
minimum_coverage: 78
show_missing: True
fail_below_threshold: True
link_missing_lines: True
Expand Down
4 changes: 3 additions & 1 deletion src/pytom_tm/__init__.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
import logging
from importlib import metadata
__version__ = metadata.version('pytom-match-pick')


try:
import cupy
except (ModuleNotFoundError, ImportError):
print('Error for template matching: cupy installation not found or not functional.')
logging.warning('Error for template matching: cupy installation not found or not functional.')
1 change: 0 additions & 1 deletion src/pytom_tm/extract.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@

plotting_available = False
try:
import matplotlib
import matplotlib.pyplot as plt
import seaborn as sns
sns.set(context='talk', style='ticks')
Expand Down
8 changes: 4 additions & 4 deletions src/pytom_tm/plotting.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,13 @@
from scipy.optimize import curve_fit
from scipy.special import erf

if find_spec("matplotlib") is None or find_spec("seaborn") is None:
try:
import matplotlib.pyplot as plt
import seaborn as sns
except ModuleNotFoundError:
raise RuntimeError(
"ROC estimation can only be done when matplotlib and seaborn are installed."
)
else:
import matplotlib.pyplot as plt
import seaborn as sns
sns.set(context="talk", style="ticks")


Expand Down
85 changes: 85 additions & 0 deletions tests/test_broken_imports.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
# No imports of pytom_tm outside of the methods
import unittest
from importlib import reload
# Mock out installed dependencies
orig_import = __import__

def module_not_found_mock(missing_name):
def import_mock(name, *args):
if name == missing_name:
raise ModuleNotFoundError(f"No module named '{name}'")
return orig_import(name, *args)
return import_mock

def cupy_import_error_mock(name, *args):
if name == 'cupy':
raise ImportError("Failed to import cupy")
return orig_import(name, *args)


class TestMissingDependencies(unittest.TestCase):

def test_missing_cupy(self):
# assert working import
with self.assertNoLogs(level='WARNING'):
import pytom_tm
cupy_not_found = module_not_found_mock('cupy')
# Test missing cupy
with unittest.mock.patch('builtins.__import__', side_effect=cupy_not_found):
with self.assertLogs(level='WARNING') as cm:
reload(pytom_tm)
self.assertEqual(len(cm.output), 1)
self.assertIn("cupy installation not found or not functional", cm.output[0])

def test_broken_cupy(self):
# assert working import
with self.assertNoLogs(level='WARNING'):
import pytom_tm
# Test cupy ImportError
with unittest.mock.patch('builtins.__import__', side_effect=cupy_import_error_mock):
with self.assertLogs(level='WARNING') as cm:
reload(pytom_tm)
self.assertEqual(len(cm.output), 1)
self.assertIn("cupy installation not found or not functional", cm.output[0])

def test_missing_matplotlib(self):
# assert working import
import pytom_tm

matplotlib_not_found = module_not_found_mock('matplotlib.pyplot')
with unittest.mock.patch('builtins.__import__', side_effect=matplotlib_not_found):
with self.assertRaisesRegex(ModuleNotFoundError, 'matplotlib'):
# only pyplot is directly imported so this should be tested
import matplotlib.pyplot as plt
# force reload
# check if we can still import pytom_tm
reload(pytom_tm)

# check if plotting is indeed disabled after reload
# (reload is needed to prevent python import caching)
self.assertFalse(reload(pytom_tm.template).plotting_available)
self.assertFalse(reload(pytom_tm.extract).plotting_available)
# assert that importing the plotting module fails completely
with self.assertRaisesRegex(RuntimeError, "matplotlib and seaborn"):
reload(pytom_tm.plotting)

def test_missing_seaborn(self):
# assert working import
import pytom_tm

seaborn_not_found = module_not_found_mock('seaborn')
with unittest.mock.patch('builtins.__import__', side_effect=seaborn_not_found):
with self.assertRaisesRegex(ModuleNotFoundError, 'seaborn'):
import seaborn
# check if we can still import pytom_tm
reload(pytom_tm)
# check if plotting is indeed disabled
# (reload is needed to prevent python import caching)
self.assertFalse(reload(pytom_tm.template).plotting_available)
self.assertFalse(reload(pytom_tm.extract).plotting_available)
# assert that importing the plotting module fails completely
with self.assertRaisesRegex(RuntimeError, "matplotlib and seaborn"):
reload(pytom_tm.plotting)