Commit 71d76f11 authored by Gregory Ashton's avatar Gregory Ashton
Browse files

Fix flake8 issues in tests and docs

- Also applies Black for future inclusion
parent 16d28028
...@@ -157,3 +157,18 @@ deploy_release: ...@@ -157,3 +157,18 @@ deploy_release:
- twine upload dist/* - twine upload dist/*
only: only:
- tags - tags
precommits-py3.7:
stage: test
image: bilbydev/v2-dockerfile-test-suite-python37
script:
- source activate python37
- mkdir -p .pip37
- pip install --upgrade pip
- pip --cache-dir=.pip37 install --upgrade bilby
- pip --cache-dir=.pip37 install .
- pip --cache-dir=.pip37 install pre-commit
# Run precommits (flake8, spellcheck, isort, no merge conflicts, etc)
- pre-commit run --all-files --verbose --show-diff-on-failure
repos:
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v2.3.0
hooks:
- id: check-merge-conflict # prevent committing files with merge conflicts
- id: flake8 # checks for flake8 errors
#- repo: https://github.com/codespell-project/codespell
# rev: v1.16.0
# hooks:
# - id: codespell # Spellchecker
# args: [-L, nd, --skip, "*.ipynb,*.html", --ignore-words=.dictionary.txt]
# exclude: ^examples/tutorials/
#- repo: https://github.com/asottile/seed-isort-config
# rev: v1.3.0
# hooks:
# - id: seed-isort-config
# args: [--application-directories, 'bilby/']
#- repo: https://github.com/pre-commit/mirrors-isort
# rev: v4.3.21
# hooks:
# - id: isort # sort imports alphabetically and separates import into sections
# args: [-w=88, -m=3, -tc, -sp=setup.cfg ]
...@@ -49,6 +49,33 @@ def my_new_function(x, y, print=False): ...@@ -49,6 +49,33 @@ def my_new_function(x, y, print=False):
5. Don't repeat yourself. If code is repeated in multiple places, wrap it up into a function. 5. Don't repeat yourself. If code is repeated in multiple places, wrap it up into a function.
6. Add tests. The C.I. is there to do the work of "checking" the code, both now and into the future. Use it. 6. Add tests. The C.I. is there to do the work of "checking" the code, both now and into the future. Use it.
## Automated code checking
In order to automate checking of the code quality, we use
[pre-commit](https://pre-commit.com/). For more details, see the documentation,
here we will give a quick-start guide:
1. Install and configure:
```console
$ pip install pre-commit # install the pre-commit package
$ cd bilby
$ pre-commit install
```
2. Now, when you run `$ git commit`, there will be a pre-commit check.
This is going to search for issues in your code: spelling, formatting, etc.
In some cases, it will automatically fix the code, in other cases, it will
print a warning. If it automatically fixed the code, you'll need to add the
changes to the index (`$ git add FILE.py`) and run `$ git commit` again. If
it didn't automatically fix the code, but still failed, it will have printed
a message as to why the commit failed. Read the message, fix the issues,
then recommit.
3. The pre-commit checks are done to avoid pushing and then failing. But, you
can skip them by running `$ git commit --no-verify`, but note that the C.I.
still does the check so you won't be able to merge until the issues are
resolved.
If you experience any issues with pre-commit, please ask for support on the
usual help channels.
## Code relevance ## Code relevance
The bilby code base is intended to be highly modular and flexible. We encourage The bilby code base is intended to be highly modular and flexible. We encourage
......
...@@ -173,5 +173,3 @@ texinfo_documents = [ ...@@ -173,5 +173,3 @@ texinfo_documents = [
] ]
numpydoc_show_class_members = False numpydoc_show_class_members = False
[flake8] [flake8]
exclude = .git,docs,build,dist,test,*__init__.py exclude = .git,docs,build,dist,test,*__init__.py
max-line-length = 120 max-line-length = 120
ignore = E129 W503 W504 W605 E203 ignore = E129 W503 W504 W605 E203 E402
[tool:pytest] [tool:pytest]
addopts = addopts =
......
...@@ -4,7 +4,6 @@ import numpy as np ...@@ -4,7 +4,6 @@ import numpy as np
class TestBaseClass(unittest.TestCase): class TestBaseClass(unittest.TestCase):
def setUp(self): def setUp(self):
self.model = calibration.Recalibrate() self.model = calibration.Recalibrate()
...@@ -12,7 +11,7 @@ class TestBaseClass(unittest.TestCase): ...@@ -12,7 +11,7 @@ class TestBaseClass(unittest.TestCase):
del self.model del self.model
def test_repr(self): def test_repr(self):
expected = 'Recalibrate(prefix={})'.format('\'recalib_\'') expected = "Recalibrate(prefix={})".format("'recalib_'")
actual = repr(self.model) actual = repr(self.model)
self.assertEqual(expected, actual) self.assertEqual(expected, actual)
...@@ -23,18 +22,22 @@ class TestBaseClass(unittest.TestCase): ...@@ -23,18 +22,22 @@ class TestBaseClass(unittest.TestCase):
class TestCubicSpline(unittest.TestCase): class TestCubicSpline(unittest.TestCase):
def setUp(self): def setUp(self):
self.prefix = 'recalib_' self.prefix = "recalib_"
self.minimum_frequency = 20 self.minimum_frequency = 20
self.maximum_frequency = 1024 self.maximum_frequency = 1024
self.n_points = 5 self.n_points = 5
self.model = calibration.CubicSpline( self.model = calibration.CubicSpline(
prefix=self.prefix, minimum_frequency=self.minimum_frequency, prefix=self.prefix,
maximum_frequency=self.maximum_frequency, n_points=self.n_points) minimum_frequency=self.minimum_frequency,
self.parameters = {'recalib_{}_{}'.format(param, ii): 0.0 maximum_frequency=self.maximum_frequency,
for ii in range(5) n_points=self.n_points,
for param in ['amplitude', 'phase']} )
self.parameters = {
"recalib_{}_{}".format(param, ii): 0.0
for ii in range(5)
for param in ["amplitude", "phase"]
}
def tearDown(self): def tearDown(self):
del self.prefix del self.prefix
...@@ -46,27 +49,28 @@ class TestCubicSpline(unittest.TestCase): ...@@ -46,27 +49,28 @@ class TestCubicSpline(unittest.TestCase):
def test_calibration_factor(self): def test_calibration_factor(self):
frequency_array = np.linspace(20, 1024, 1000) frequency_array = np.linspace(20, 1024, 1000)
cal_factor = self.model.get_calibration_factor(frequency_array, cal_factor = self.model.get_calibration_factor(
**self.parameters) frequency_array, **self.parameters
)
assert np.alltrue(cal_factor.real == np.ones_like(frequency_array)) assert np.alltrue(cal_factor.real == np.ones_like(frequency_array))
def test_repr(self): def test_repr(self):
expected = 'CubicSpline(prefix=\'{}\', minimum_frequency={}, maximum_frequency={}, n_points={})'\ expected = "CubicSpline(prefix='{}', minimum_frequency={}, maximum_frequency={}, n_points={})".format(
.format(self.prefix, self.minimum_frequency, self.maximum_frequency, self.n_points) self.prefix, self.minimum_frequency, self.maximum_frequency, self.n_points
)
actual = repr(self.model) actual = repr(self.model)
self.assertEqual(expected, actual) self.assertEqual(expected, actual)
class TestCubicSplineRequiresFourNodes(unittest.TestCase): class TestCubicSplineRequiresFourNodes(unittest.TestCase):
def test_cannot_instantiate_with_too_few_nodes(self): def test_cannot_instantiate_with_too_few_nodes(self):
for ii in range(6): for ii in range(6):
if ii < 4: if ii < 4:
with self.assertRaises(ValueError): with self.assertRaises(ValueError):
calibration.CubicSpline('test', 1, 10, ii) calibration.CubicSpline("test", 1, 10, ii)
else: else:
calibration.CubicSpline('test', 1, 10, ii) calibration.CubicSpline("test", 1, 10, ii)
if __name__ == '__main__': if __name__ == "__main__":
unittest.main() unittest.main()
import os import os
import sys import sys
sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), '..')))
import bilby sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), "..")))
import bilby # noqa
This diff is collapsed.
...@@ -6,18 +6,17 @@ from bilby.gw import cosmology ...@@ -6,18 +6,17 @@ from bilby.gw import cosmology
class TestSetCosmology(unittest.TestCase): class TestSetCosmology(unittest.TestCase):
def setUp(self): def setUp(self):
pass pass
def test_setting_cosmology_with_string(self): def test_setting_cosmology_with_string(self):
cosmology.set_cosmology('WMAP9') cosmology.set_cosmology("WMAP9")
self.assertEqual(cosmology.COSMOLOGY[1], 'WMAP9') self.assertEqual(cosmology.COSMOLOGY[1], "WMAP9")
cosmology.set_cosmology('Planck15') cosmology.set_cosmology("Planck15")
def test_setting_cosmology_with_astropy_object(self): def test_setting_cosmology_with_astropy_object(self):
cosmology.set_cosmology(WMAP9) cosmology.set_cosmology(WMAP9)
self.assertEqual(cosmology.COSMOLOGY[1], 'WMAP9') self.assertEqual(cosmology.COSMOLOGY[1], "WMAP9")
cosmology.set_cosmology(Planck15) cosmology.set_cosmology(Planck15)
def test_setting_cosmology_with_default(self): def test_setting_cosmology_with_default(self):
...@@ -27,30 +26,29 @@ class TestSetCosmology(unittest.TestCase): ...@@ -27,30 +26,29 @@ class TestSetCosmology(unittest.TestCase):
def test_setting_cosmology_with_flat_lambda_cdm_dict(self): def test_setting_cosmology_with_flat_lambda_cdm_dict(self):
cosmo_dict = dict(H0=67.7, Om0=0.3) cosmo_dict = dict(H0=67.7, Om0=0.3)
cosmology.set_cosmology(cosmo_dict) cosmology.set_cosmology(cosmo_dict)
self.assertEqual(cosmology.COSMOLOGY[1][:13], 'FlatLambdaCDM') self.assertEqual(cosmology.COSMOLOGY[1][:13], "FlatLambdaCDM")
def test_setting_cosmology_with_lambda_cdm_dict(self): def test_setting_cosmology_with_lambda_cdm_dict(self):
cosmo_dict = dict(H0=67.7, Om0=0.3, Ode0=0.7) cosmo_dict = dict(H0=67.7, Om0=0.3, Ode0=0.7)
cosmology.set_cosmology(cosmo_dict) cosmology.set_cosmology(cosmo_dict)
self.assertEqual(cosmology.COSMOLOGY[1][:9], 'LambdaCDM') self.assertEqual(cosmology.COSMOLOGY[1][:9], "LambdaCDM")
def test_setting_cosmology_with_w_cdm_dict(self): def test_setting_cosmology_with_w_cdm_dict(self):
cosmo_dict = dict(H0=67.7, Om0=0.3, Ode0=0.7, w0=-1.0) cosmo_dict = dict(H0=67.7, Om0=0.3, Ode0=0.7, w0=-1.0)
cosmology.set_cosmology(cosmo_dict) cosmology.set_cosmology(cosmo_dict)
self.assertEqual(cosmology.COSMOLOGY[1][:4], 'wCDM') self.assertEqual(cosmology.COSMOLOGY[1][:4], "wCDM")
class TestGetCosmology(unittest.TestCase): class TestGetCosmology(unittest.TestCase):
def setUp(self): def setUp(self):
pass pass
def test_getting_cosmology_with_string(self): def test_getting_cosmology_with_string(self):
self.assertEqual(cosmology.get_cosmology('WMAP9').name, 'WMAP9') self.assertEqual(cosmology.get_cosmology("WMAP9").name, "WMAP9")
def test_getting_cosmology_with_default(self): def test_getting_cosmology_with_default(self):
self.assertEqual(cosmology.get_cosmology(), cosmology.COSMOLOGY[0]) self.assertEqual(cosmology.get_cosmology(), cosmology.COSMOLOGY[0])
if __name__ == '__main__': if __name__ == "__main__":
unittest.main() unittest.main()
This diff is collapsed.
from __future__ import absolute_import from __future__ import absolute_import
import matplotlib import matplotlib
matplotlib.use('Agg')
matplotlib.use("Agg")
import unittest import unittest
import os import os
...@@ -12,14 +13,14 @@ from past.builtins import execfile ...@@ -12,14 +13,14 @@ from past.builtins import execfile
import bilby.core.utils import bilby.core.utils
# Imported to ensure the examples run # Imported to ensure the examples run
import numpy as np import numpy as np # noqa: F401
import inspect import inspect # noqa: F401
bilby.core.utils.command_line_args.bilby_test_mode = True bilby.core.utils.command_line_args.bilby_test_mode = True
class Test(unittest.TestCase): class Test(unittest.TestCase):
outdir = 'outdir' outdir = "outdir"
dir_path = os.path.dirname(os.path.realpath(__file__)) dir_path = os.path.dirname(os.path.realpath(__file__))
dir_path = os.path.abspath(os.path.join(dir_path, os.path.pardir)) dir_path = os.path.abspath(os.path.join(dir_path, os.path.pardir))
...@@ -29,8 +30,7 @@ class Test(unittest.TestCase): ...@@ -29,8 +30,7 @@ class Test(unittest.TestCase):
try: try:
shutil.rmtree(self.outdir) shutil.rmtree(self.outdir)
except OSError: except OSError:
logging.warning( logging.warning("{} not removed prior to tests".format(self.outdir))
"{} not removed prior to tests".format(self.outdir))
@classmethod @classmethod
def tearDownClass(self): def tearDownClass(self):
...@@ -38,20 +38,18 @@ class Test(unittest.TestCase): ...@@ -38,20 +38,18 @@ class Test(unittest.TestCase):
try: try:
shutil.rmtree(self.outdir) shutil.rmtree(self.outdir)
except OSError: except OSError:
logging.warning( logging.warning("{} not removed prior to tests".format(self.outdir))
"{} not removed prior to tests".format(self.outdir))
def test_examples(self): def test_examples(self):
""" Loop over examples to check they run """ """ Loop over examples to check they run """
examples = ['examples/core_examples/linear_regression.py', examples = [
'examples/core_examples/linear_regression_unknown_noise.py', "examples/core_examples/linear_regression.py",
] "examples/core_examples/linear_regression_unknown_noise.py",
]
for filename in examples: for filename in examples:
print("Testing {}".format(filename)) print("Testing {}".format(filename))
execfile(filename) execfile(filename)
if __name__ == '__main__': if __name__ == "__main__":
unittest.main() unittest.main()
...@@ -2,10 +2,8 @@ from __future__ import absolute_import, division ...@@ -2,10 +2,8 @@ from __future__ import absolute_import, division
import unittest import unittest
import numpy as np import numpy as np
import pandas as pd
import shutil import shutil
import os import os
import json
from scipy.stats import multivariate_normal from scipy.stats import multivariate_normal
import bilby import bilby
...@@ -30,32 +28,41 @@ class MultiGaussian(bilby.Likelihood): ...@@ -30,32 +28,41 @@ class MultiGaussian(bilby.Likelihood):
class TestGrid(unittest.TestCase): class TestGrid(unittest.TestCase):
def setUp(self): def setUp(self):
np.random.seed(7) np.random.seed(7)
# set 2D multivariate Gaussian (zero mean, unit variance) # set 2D multivariate Gaussian (zero mean, unit variance)
self.mus = [0., 0.] self.mus = [0.0, 0.0]
self.cov = [[1., 0.], [0., 1.]] self.cov = [[1.0, 0.0], [0.0, 1.0]]
dim = len(self.mus) dim = len(self.mus)
self.likelihood = MultiGaussian(self.mus, self.cov) self.likelihood = MultiGaussian(self.mus, self.cov)
# set priors out to +/- 5 sigma # set priors out to +/- 5 sigma
self.priors = bilby.core.prior.PriorDict() self.priors = bilby.core.prior.PriorDict()
self.priors.update( self.priors.update(
{"x{0}".format(i): bilby.core.prior.Uniform(-5, 5, "x{0}".format(i)) for i in range(dim)} {
"x{0}".format(i): bilby.core.prior.Uniform(-5, 5, "x{0}".format(i))
for i in range(dim)
}
) )
# expected evidence integral should be (1/V) where V is the prior volume # expected evidence integral should be (1/V) where V is the prior volume
log_prior_vol = np.sum(np.log([prior.maximum - prior.minimum for key, prior in self.priors.items()])) log_prior_vol = np.sum(
np.log(
[prior.maximum - prior.minimum for key, prior in self.priors.items()]
)
)
self.expected_ln_evidence = -log_prior_vol self.expected_ln_evidence = -log_prior_vol
self.grid_size = 100 self.grid_size = 100
grid = bilby.core.grid.Grid( grid = bilby.core.grid.Grid(
label='label', outdir='outdir', priors=self.priors, label="label",
grid_size=self.grid_size, likelihood=self.likelihood, outdir="outdir",
save=True priors=self.priors,
grid_size=self.grid_size,
likelihood=self.likelihood,
save=True,
) )
self.grid = grid self.grid = grid
...@@ -71,29 +78,33 @@ class TestGrid(unittest.TestCase): ...@@ -71,29 +78,33 @@ class TestGrid(unittest.TestCase):
pass pass
def test_grid_file_name_default(self): def test_grid_file_name_default(self):
outdir = 'outdir' outdir = "outdir"
label = 'label' label = "label"
self.assertEqual(bilby.core.grid.grid_file_name(outdir, label), self.assertEqual(
'{}/{}_grid.json'.format(outdir, label)) bilby.core.grid.grid_file_name(outdir, label),
self.assertEqual(bilby.core.grid.grid_file_name(outdir, label, True), "{}/{}_grid.json".format(outdir, label),
'{}/{}_grid.json.gz'.format(outdir, label)) )
self.assertEqual(
bilby.core.grid.grid_file_name(outdir, label, True),
"{}/{}_grid.json.gz".format(outdir, label),
)
def test_fail_save_and_load(self): def test_fail_save_and_load(self):
with self.assertRaises(ValueError): with self.assertRaises(ValueError):
bilby.core.grid.Grid.read() bilby.core.grid.Grid.read()
with self.assertRaises(IOError): with self.assertRaises(IOError):
bilby.core.grid.Grid.read(filename='not/a/file.json') bilby.core.grid.Grid.read(filename="not/a/file.json")
def test_fail_marginalize(self): def test_fail_marginalize(self):
with self.assertRaises(TypeError): with self.assertRaises(TypeError):
self.grid.marginalize_posterior(parameters=2.4) self.grid.marginalize_posterior(parameters=2.4)
with self.assertRaises(TypeError): with self.assertRaises(TypeError):
self.grid.marginalize_posterior(not_parameters=4.7) self.grid.marginalize_posterior(not_parameters=4.7)
with self.assertRaises(ValueError): with self.assertRaises(ValueError):
self.grid.marginalize_posterior(parameters='jkgsd') self.grid.marginalize_posterior(parameters="jkgsd")
def test_parameter_names(self): def test_parameter_names(self):
assert list(self.priors.keys()) == self.grid.parameter_names assert list(self.priors.keys()) == self.grid.parameter_names
...@@ -102,94 +113,150 @@ class TestGrid(unittest.TestCase): ...@@ -102,94 +113,150 @@ class TestGrid(unittest.TestCase):
def test_no_marginalization(self): def test_no_marginalization(self):
# test arrays are the same if no parameters are given to marginalize # test arrays are the same if no parameters are given to marginalize
# over # over
assert np.array_equal(self.grid.ln_likelihood, assert np.array_equal(
self.grid.marginalize_ln_likelihood(not_parameters=self.grid.parameter_names)) self.grid.ln_likelihood,
self.grid.marginalize_ln_likelihood(
not_parameters=self.grid.parameter_names
),
)
def test_marginalization_shapes(self): def test_marginalization_shapes(self):
assert len(self.grid.marginalize_ln_likelihood().shape) == 0 assert len(self.grid.marginalize_ln_likelihood().shape) == 0
marg1 = self.grid.marginalize_ln_likelihood(parameters=self.grid.parameter_names[0]) marg1 = self.grid.marginalize_ln_likelihood(
parameters=self.grid.parameter_names[0]
)
assert marg1.shape == (self.grid_size,) assert marg1.shape == (self.grid_size,)
marg2 = self.grid.marginalize_ln_likelihood(parameters=self.grid.parameter_names[1]) marg2 = self.grid.marginalize_ln_likelihood(
parameters=self.grid.parameter_names[1]
)
assert marg2.shape == (self.grid_size,) assert marg2.shape == (self.grid_size,)
assert self.grid.ln_likelihood.shape == (self.grid_size, self.grid_size) assert self.grid.ln_likelihood.shape == (self.grid_size, self.grid_size)
assert self.grid.ln_posterior.shape == (self.grid_size, self.grid_size) assert self.grid.ln_posterior.shape == (self.grid_size, self.grid_size)
def test_marginalization_opposite(self): def test_marginalization_opposite(self):
assert np.array_equal(self.grid.marginalize_ln_likelihood(parameters=self.grid.parameter_names[0]), assert np.array_equal(
self.grid.marginalize_ln_likelihood(not_parameters=self.grid.parameter_names[1])) self.grid.marginalize_ln_likelihood(
assert np.array_equal(self.grid.marginalize_ln_likelihood(parameters=self.grid.parameter_names[1]), parameters=self.grid.parameter_names[0]
self.grid.marginalize_ln_likelihood(not_parameters=self.grid.parameter_names[0])) ),