diff --git a/.coveragerc b/.coveragerc index b680af37e8..84e18fdcb3 100644 --- a/.coveragerc +++ b/.coveragerc @@ -1,3 +1,7 @@ [run] omit = zarr/meta_v1.py +[report] +exclude_lines = + pragma: no cover + pragma: ${PY_MAJOR_VERSION} no cover diff --git a/tox.ini b/tox.ini index f98a40b917..96bff14383 100644 --- a/tox.ini +++ b/tox.ini @@ -9,12 +9,15 @@ envlist = py27, py34, py35, py36, docs [testenv] setenv = PYTHONHASHSEED = 42 + # hooks for coverage exclusions based on Python major version + py34,py35,py36: PY_MAJOR_VERSION = py3 + py27: PY_MAJOR_VERSION = py2 commands = - py27,py34,py35: nosetests -v zarr + py27,py34,py35: nosetests -v --with-coverage --cover-erase --cover-package=zarr zarr py36: nosetests -v --with-coverage --cover-erase --cover-package=zarr --with-doctest --doctest-options=+NORMALIZE_WHITESPACE,+ELLIPSIS zarr py36: python -m doctest -o NORMALIZE_WHITESPACE -o ELLIPSIS docs/tutorial.rst docs/spec/v2.rst py36: flake8 --max-line-length=100 zarr - py36: coverage report -m + coverage report -m deps = -rrequirements_dev.txt diff --git a/zarr/compat.py b/zarr/compat.py index ee0d7d221c..01fc4636ea 100644 --- a/zarr/compat.py +++ b/zarr/compat.py @@ -7,13 +7,13 @@ PY2 = sys.version_info[0] == 2 -if PY2: # pragma: no cover +if PY2: # pragma: py3 no cover text_type = unicode binary_type = str reduce = reduce -else: +else: # pragma: py2 no cover text_type = str binary_type = bytes diff --git a/zarr/errors.py b/zarr/errors.py index f1baf429e6..82c9306ca7 100644 --- a/zarr/errors.py +++ b/zarr/errors.py @@ -5,12 +5,12 @@ from zarr.compat import PY2 -if PY2: # pragma: no cover +if PY2: # pragma: py3 no cover class PermissionError(Exception): pass -else: +else: # pragma: py2 no cover PermissionError = PermissionError diff --git a/zarr/meta.py b/zarr/meta.py index 4831d402e9..0eefabb0f4 100644 --- a/zarr/meta.py +++ b/zarr/meta.py @@ -66,11 +66,11 @@ def _decode_dtype_descr(d): # need to convert list of lists to list of tuples if isinstance(d, list): # recurse to handle nested structures - if PY2: # pragma: no cover + if PY2: # pragma: py3 no cover # under PY2 numpy rejects unicode field names d = [(f.encode('ascii'), _decode_dtype_descr(v)) for f, v in d] - else: + else: # pragma: py2 no cover d = [(f, _decode_dtype_descr(v)) for f, v in d] return d diff --git a/zarr/meta_v1.py b/zarr/meta_v1.py index 05a055cc76..50474359cd 100644 --- a/zarr/meta_v1.py +++ b/zarr/meta_v1.py @@ -60,7 +60,7 @@ def _decode_dtype_descr(d): # need to convert list of lists to list of tuples if isinstance(d, list): # recurse to handle nested structures - if PY2: # pragma: no cover + if PY2: # under PY2 numpy rejects unicode field names d = [(f.encode('ascii'), _decode_dtype_descr(v)) for f, v in d] diff --git a/zarr/storage.py b/zarr/storage.py index aa6e949139..af6df563ed 100644 --- a/zarr/storage.py +++ b/zarr/storage.py @@ -375,13 +375,13 @@ def ensure_bytes(s): if isinstance(s, binary_type): return s if isinstance(s, np.ndarray): - if PY2: # pragma: no cover + if PY2: # pragma: py3 no cover return s.tostring(order='Any') - else: + else: # pragma: py2 no cover return s.tobytes(order='Any') if hasattr(s, 'tobytes'): return s.tobytes() - if PY2 and hasattr(s, 'tostring'): # pragma: no cover + if PY2 and hasattr(s, 'tostring'): # pragma: py3 no cover return s.tostring() return memoryview(s).tobytes() diff --git a/zarr/tests/test_core.py b/zarr/tests/test_core.py index bc45218f9d..89c1c31f88 100644 --- a/zarr/tests/test_core.py +++ b/zarr/tests/test_core.py @@ -742,7 +742,8 @@ def create_array(self, read_only=False, **kwargs): return Array(store, read_only=read_only) -if not PY2: +# TODO can we rely on backports and remove the PY2 exclusion? +if not PY2: # pragma: py2 no cover from zarr.codecs import LZMA diff --git a/zarr/tests/test_filters.py b/zarr/tests/test_filters.py index 6da5391eaa..f9c9d04434 100644 --- a/zarr/tests/test_filters.py +++ b/zarr/tests/test_filters.py @@ -20,7 +20,8 @@ Blosc(), ] -if not PY2: +# TODO can we rely on backports and remove PY2 exclusion? +if not PY2: # pragma: py2 no cover from zarr.codecs import LZMA compressors.append(LZMA()) diff --git a/zarr/tests/test_hierarchy.py b/zarr/tests/test_hierarchy.py index 4ab1073dae..ae7adf380b 100644 --- a/zarr/tests/test_hierarchy.py +++ b/zarr/tests/test_hierarchy.py @@ -15,7 +15,7 @@ from zarr.storage import DictStore, DirectoryStore, ZipStore, init_group, \ - init_array, attrs_key, array_meta_key, group_meta_key + init_array, attrs_key, array_meta_key, group_meta_key, atexit_rmtree from zarr.core import Array from zarr.hierarchy import Group, group, open_group from zarr.attrs import Attributes @@ -591,15 +591,13 @@ def visitor4(name, obj): # visitor filter tests def visitor0(val, *args): name = getattr(val, "path", val) - if name == "a/b/c/d": return True # pragma: no cover def visitor1(val, *args): name = getattr(val, "path", val) - if name == "a/b/c": - return True # pragma: no cover + return True eq(None, g1.visit(visitor0)) eq(None, g1.visitkeys(visitor0)) @@ -783,18 +781,12 @@ def create_store(): return DictStore(), None -def rmtree(p, f=shutil.rmtree, g=os.path.isdir): # pragma: no cover - """Version of rmtree that will work atexit and only remove if directory.""" - if g(p): - f(p) - - class TestGroupWithDirectoryStore(TestGroup): @staticmethod def create_store(): path = tempfile.mkdtemp() - atexit.register(rmtree, path) + atexit.register(atexit_rmtree, path) store = DirectoryStore(path) return store, None diff --git a/zarr/tests/test_meta.py b/zarr/tests/test_meta.py index c4c0a09c02..8c1d67f2b0 100644 --- a/zarr/tests/test_meta.py +++ b/zarr/tests/test_meta.py @@ -14,8 +14,8 @@ from zarr.codecs import Delta, Zlib, Blosc -def assert_json_eq(expect, actual): # pragma: no cover - if isinstance(expect, binary_type): +def assert_json_eq(expect, actual): + if isinstance(expect, binary_type): # pragma: py3 no cover expect = text_type(expect, 'ascii') if isinstance(actual, binary_type): actual = text_type(actual, 'ascii') diff --git a/zarr/tests/test_storage.py b/zarr/tests/test_storage.py index 8449cec85e..4182c358ac 100644 --- a/zarr/tests/test_storage.py +++ b/zarr/tests/test_storage.py @@ -17,7 +17,7 @@ from zarr.storage import init_array, array_meta_key, attrs_key, DictStore, \ DirectoryStore, ZipStore, init_group, group_meta_key, getsize, \ - migrate_1to2, TempStore + migrate_1to2, TempStore, atexit_rmtree from zarr.meta import decode_array_metadata, encode_array_metadata, \ ZARR_FORMAT, decode_group_metadata, encode_group_metadata from zarr.compat import text_type @@ -574,17 +574,11 @@ def test_getsize_ext(self): eq(-1, store.getsize('b')) -def rmtree(p, f=shutil.rmtree, g=os.path.isdir): # pragma: no cover - """Version of rmtree that will work atexit and only remove if directory.""" - if g(p): - f(p) - - class TestDirectoryStore(StoreTests, unittest.TestCase): def create_store(self): path = tempfile.mkdtemp() - atexit.register(rmtree, path) + atexit.register(atexit_rmtree, path) store = DirectoryStore(path) return store diff --git a/zarr/util.py b/zarr/util.py index c5e093997d..51b65d06d2 100644 --- a/zarr/util.py +++ b/zarr/util.py @@ -273,7 +273,7 @@ def normalize_order(order): def normalize_storage_path(path): # handle bytes - if not PY2 and isinstance(path, bytes): + if not PY2 and isinstance(path, bytes): # pragma: py2 no cover path = str(path, 'ascii') # ensure str @@ -317,11 +317,11 @@ def normalize_storage_path(path): def buffer_size(v): from array import array as _stdlib_array - if PY2 and isinstance(v, _stdlib_array): # pragma: no cover + if PY2 and isinstance(v, _stdlib_array): # pragma: py3 no cover # special case array.array because does not support buffer # interface in PY2 return v.buffer_info()[1] * v.itemsize - else: + else: # pragma: py2 no cover v = memoryview(v) return reduce(operator.mul, v.shape) * v.itemsize