From de432247455a077294ae645bbb149f81e1b76b44 Mon Sep 17 00:00:00 2001 From: Peter Law Date: Sat, 27 Jan 2024 17:11:41 +0000 Subject: [PATCH 1/3] Drop support for testing on Python 2 This seems to have mostly gone away a while back, however some stuff remained (unclear how working that stuff was). I'm about to add typing annotations and that'll be much easier if we don't need to support Python 2 at all. --- test.py | 9 --------- 1 file changed, 9 deletions(-) diff --git a/test.py b/test.py index ac8ed61..12fec8e 100755 --- a/test.py +++ b/test.py @@ -14,12 +14,6 @@ import pyroaring from pyroaring import BitMap, FrozenBitMap -is_python2 = sys.version_info < (3, 0) - -try: # Python2 compatibility - range = xrange -except NameError: - pass settings.register_profile("ci", settings( max_examples=100, deadline=None)) @@ -537,7 +531,6 @@ def test_intersection_update(self, initial_values, all_values, cow): self.assertEqual(expected_result, self.initial_bitmap) self.assertEqual(type(expected_result), type(self.initial_bitmap)) - @unittest.skipIf(is_python2, 'https://github.com/Ezibenroc/PyRoaringBitMap/pull/38#issuecomment-418262391') @given(bitmap_cls, st.data(), hyp_many_collections, st.booleans()) def test_union(self, cls, data, all_values, cow): classes = [data.draw(bitmap_cls) for _ in range(len(all_values))] @@ -548,7 +541,6 @@ def test_union(self, cls, data, all_values, cow): lambda x, y: x | y, self.all_bitmaps) self.assertEqual(expected_result, result) - @unittest.skipIf(is_python2, 'https://github.com/Ezibenroc/PyRoaringBitMap/pull/38#issuecomment-418262391') @given(bitmap_cls, st.data(), hyp_many_collections, st.booleans()) def test_intersection(self, cls, data, all_values, cow): classes = [data.draw(bitmap_cls) for _ in range(len(all_values))] @@ -559,7 +551,6 @@ def test_intersection(self, cls, data, all_values, cow): lambda x, y: x & y, self.all_bitmaps) self.assertEqual(expected_result, result) - @unittest.skipIf(is_python2, 'https://github.com/Ezibenroc/PyRoaringBitMap/pull/38#issuecomment-418262391') @given(bitmap_cls, st.data(), hyp_many_collections, st.booleans()) def test_difference(self, cls, data, all_values, cow): classes = [data.draw(bitmap_cls) for _ in range(len(all_values))] From c66c137fb4b8e845582f69644d0f4ffdd61797d2 Mon Sep 17 00:00:00 2001 From: Peter Law Date: Sat, 27 Jan 2024 17:14:13 +0000 Subject: [PATCH 2/3] Avoid overloading this variable I'm about to add type checking here, mypy would complain about this re-use with different types. --- test.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test.py b/test.py index 12fec8e..e5b217b 100755 --- a/test.py +++ b/test.py @@ -1412,8 +1412,8 @@ def test_large_list(self, cls, collection): bm = cls(collection) s = repr(bm) nondigits = set(s) - set('0123456789\n.') - for i in nondigits: - s = s.replace(i, ' ') + for x in nondigits: + s = s.replace(x, ' ') small, large = s.split('...') small_ints = [int(i) for i in small.split()] From 7c2797c40c97e0587110540526533d32edf2598f Mon Sep 17 00:00:00 2001 From: Peter Law Date: Sat, 27 Jan 2024 17:30:42 +0000 Subject: [PATCH 3/3] Add linting for Python files This hopefully makes these files slightly clearer, though I'm mostly adding this so there's somewhere to hook calling mypy as part of adding type stubs. --- cydoctest.py | 13 ++-- docs/conf.py | 9 ++- download_amalgamation.py | 7 +- quick_bench.py | 18 ++--- setup.cfg | 30 +++++++++ setup.py | 20 +++--- test.py | 139 +++++++++++++++++++-------------------- tox.ini | 9 +++ 8 files changed, 140 insertions(+), 105 deletions(-) create mode 100644 setup.cfg diff --git a/cydoctest.py b/cydoctest.py index fd22a4b..51173ad 100644 --- a/cydoctest.py +++ b/cydoctest.py @@ -18,6 +18,7 @@ import doctest import inspect + def _from_module(module, object): """ Return true if the given object is defined in the given module. @@ -33,10 +34,11 @@ def _from_module(module, object): elif hasattr(object, '__module__'): return module.__name__ == object.__module__ elif isinstance(object, property): - return True # [XX] no way not be sure. + return True # [XX] no way not be sure. else: raise ValueError("object must be a class or function") + def fix_module_doctest(module): """ Extract docstrings from cython functions, that would be skipped by doctest @@ -44,9 +46,10 @@ def fix_module_doctest(module): """ module.__test__ = {} for name in dir(module): - value = getattr(module, name) - if inspect.isbuiltin(value) and isinstance(value.__doc__, str) and _from_module(module, value): - module.__test__[name] = value.__doc__ + value = getattr(module, name) + if inspect.isbuiltin(value) and isinstance(value.__doc__, str) and _from_module(module, value): + module.__test__[name] = value.__doc__ + def testmod(m=None, *args, **kwargs): """ @@ -62,4 +65,4 @@ def testmod(m=None, *args, **kwargs): if __name__ == "__main__": import pyroaring - testmod(pyroaring) \ No newline at end of file + testmod(pyroaring) diff --git a/docs/conf.py b/docs/conf.py index 6464313..2c68b39 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -31,11 +31,13 @@ # Add any Sphinx extension module names here, as strings. They can be # extensions coming with Sphinx (named 'sphinx.ext.*') or your custom # ones. -extensions = ['sphinx.ext.autodoc', +extensions = [ + 'sphinx.ext.autodoc', 'sphinx.ext.doctest', 'sphinx.ext.coverage', 'sphinx.ext.mathjax', - 'sphinx.ext.viewcode'] + 'sphinx.ext.viewcode', +] # Add any paths that contain templates here, relative to this directory. templates_path = ['_templates'] @@ -156,6 +158,3 @@ author, 'pyroaring', 'One line description of project.', 'Miscellaneous'), ] - - - diff --git a/download_amalgamation.py b/download_amalgamation.py index 4eeb9a9..6bf0295 100644 --- a/download_amalgamation.py +++ b/download_amalgamation.py @@ -7,8 +7,8 @@ """ import os -from urllib.request import urlretrieve import sys +from urllib.request import urlretrieve version = sys.argv[1] @@ -19,8 +19,7 @@ files = ["roaring.c", "roaring.h"] for file in files: - r = urlretrieve(release + file, os.path.join("pyroaring", file)) + r = urlretrieve(release + file, os.path.join("pyroaring", file)) with open(os.path.join("pyroaring", "croaring_version.pxi"), "w") as f: - f.write(f"__croaring_version__ = \"{version}\"") - + f.write(f"__croaring_version__ = \"{version}\"") diff --git a/quick_bench.py b/quick_bench.py index 17c0ee6..bede7a8 100755 --- a/quick_bench.py +++ b/quick_bench.py @@ -1,9 +1,11 @@ #! /usr/bin/env python3 import sys -import timeit -from pandas import DataFrame, Series import random +import timeit + +from pandas import Series, DataFrame + try: import tabulate has_tabulate = True @@ -17,7 +19,7 @@ nb_exp = 30 size = int(1e6) density = 0.125 -universe_size = int(size/density) +universe_size = int(size / density) try: from roaringbitmap import RoaringBitmap @@ -41,20 +43,20 @@ sys.stderr.write(' see https://github.com/sunzhaoping/python-croaring\n') import_str = 'import array, pickle; from __main__ import %s' % (','.join( - ['get_list', 'get_range', 'random', 'size', 'universe_size'] + - [cls.__name__ for cls in classes.values() if cls is not set])) + ['get_list', 'get_range', 'random', 'size', 'universe_size'] + + [cls.__name__ for cls in classes.values() if cls is not set])) def run_exp(stmt, setup, number): setup = '%s ; %s' % (import_str, setup) try: - return timeit.timeit(stmt=stmt, setup=setup, number=number)/number - except Exception as e: + return timeit.timeit(stmt=stmt, setup=setup, number=number) / number + except Exception: return float('nan') def get_range(): - r = (0, universe_size, int(1/density)) + r = (0, universe_size, int(1 / density)) try: return xrange(*r) except NameError: diff --git a/setup.cfg b/setup.cfg new file mode 100644 index 0000000..081dd9c --- /dev/null +++ b/setup.cfg @@ -0,0 +1,30 @@ +[flake8] +exclude = + .eggs + .git + .pybuild + .tox + __pycache__ + build + dist +ignore = + # W503 and W504 conflict; ignore the one that disagrees with recent PEP8. + W503 + +# try to keep it reasonable, but this allows us to push it a bit when needed. +max_line_length = 150 + +noqa-require-code = true + + +[isort] +atomic = True +balanced_wrapping = True +combine_as_imports = True +include_trailing_comma = True +length_sort = True +multi_line_output = 3 +order_by_type = False + +default_section = THIRDPARTY +sections = FUTURE,STDLIB,THIRDPARTY,FIRSTPARTY,LOCALFOLDER diff --git a/setup.py b/setup.py index 74c860f..c1511da 100755 --- a/setup.py +++ b/setup.py @@ -1,13 +1,11 @@ #! /usr/bin/env python3 -from setuptools import setup -from setuptools.extension import Extension -from distutils.sysconfig import get_config_vars import os -import sys -import subprocess import platform +from distutils.sysconfig import get_config_vars +from setuptools import setup +from setuptools.extension import Extension PKG_DIR = 'pyroaring' @@ -17,7 +15,7 @@ # Read version file from the src with open("pyroaring/version.pxi") as fp: exec(fp.read()) - VERSION = __version__ + VERSION = __version__ # noqa: F821 # Remove -Wstrict-prototypes option @@ -25,7 +23,7 @@ if not PLATFORM_WINDOWS: cfg_vars = get_config_vars() for key, value in cfg_vars.items(): - if type(value) == str: + if type(value) is str: cfg_vars[key] = value.replace("-Wstrict-prototypes", "") try: @@ -40,7 +38,7 @@ pyroaring_module = Extension( 'pyroaring', sources=[os.path.join(PKG_DIR, 'pyroaring.pyx'), os.path.join(PKG_DIR, 'roaring.c')], - language='c++' + language='c++', ) libraries = None else: @@ -59,14 +57,14 @@ # also creates troubles under macOS with pip installs and requires ugly workarounds. # The best way to handle people who want to use -march=native is to ask them # to pass ARCHI=native to their build process. - #else: + # else: # compile_args.append('-march=native') pyroaring_module = Extension( 'pyroaring', sources=[os.path.join(PKG_DIR, 'pyroaring.pyx')], extra_compile_args=compile_args + ["-std=c++11"], - language='c++' + language='c++', ) # Because we compile croaring with a c compiler with sometimes incompatible arguments, @@ -76,7 +74,7 @@ 'croaring', { 'sources': [os.path.join(PKG_DIR, 'roaring.c')], - "extra_compile_args": compile_args + ["-std=c11"] + "extra_compile_args": compile_args + ["-std=c11"], }, ) libraries = [croaring] diff --git a/test.py b/test.py index e5b217b..5b30362 100755 --- a/test.py +++ b/test.py @@ -1,20 +1,21 @@ #! /usr/bin/env python3 -import unittest -import random -import functools -import operator import os +import re import sys +import array import pickle -import re -from hypothesis import given, settings, Verbosity, errors, HealthCheck, assume +import random +import operator +import unittest +import functools + import hypothesis.strategies as st -import array +from hypothesis import given, assume, errors, settings, Verbosity, HealthCheck + import pyroaring from pyroaring import BitMap, FrozenBitMap - settings.register_profile("ci", settings( max_examples=100, deadline=None)) settings.register_profile("dev", settings(max_examples=10, deadline=None)) @@ -27,32 +28,32 @@ sys.exit('Unknown hypothesis profile: %s.' % env) uint18 = st.integers(min_value=0, max_value=2**18) -uint32 = st.integers(min_value=0, max_value=2**32-1) -uint64 = st.integers(min_value=0, max_value=2**64-1) -large_uint64 = st.integers(min_value=2**32, max_value=2**64-1) -integer = st.integers(min_value=0, max_value=2**31-1) -int64 = st.integers(min_value=-2**63, max_value=2**63-1) +uint32 = st.integers(min_value=0, max_value=2**32 - 1) +uint64 = st.integers(min_value=0, max_value=2**64 - 1) +large_uint64 = st.integers(min_value=2**32, max_value=2**64 - 1) +integer = st.integers(min_value=0, max_value=2**31 - 1) +int64 = st.integers(min_value=-2**63, max_value=2**63 - 1) range_max_size = 2**18 range_big_step = uint18.flatmap(lambda n: st.builds(range, st.just(n), st.integers( - min_value=n+1, max_value=n+range_max_size), - st.integers(min_value=2**8, max_value=range_max_size//8))) + min_value=n + 1, max_value=n + range_max_size), + st.integers(min_value=2**8, max_value=range_max_size // 8))) range_small_step = uint18.flatmap(lambda n: st.builds(range, st.just(n), st.integers( - min_value=n+1, max_value=n+range_max_size), + min_value=n + 1, max_value=n + range_max_size), st.integers(min_value=1, max_value=2**8))) range_power2_step = uint18.flatmap(lambda n: st.builds(range, st.just(n), st.integers( - min_value=n+1, max_value=n+range_max_size), + min_value=n + 1, max_value=n + range_max_size), st.integers(min_value=0, max_value=8).flatmap( - lambda n: st.just(2**n) + lambda n: st.just(2**n), ))) hyp_range = range_big_step | range_small_step | range_power2_step | st.sampled_from( @@ -69,7 +70,7 @@ class Util(unittest.TestCase): comparison_set = random.sample( - range(2**8), 100) + random.sample(range(2**31-1), 50) + range(2**8), 100) + random.sample(range(2**31 - 1), 50) def compare_with_set(self, bitmap, expected_set): self.assertEqual(len(bitmap), len(expected_set)) @@ -119,23 +120,23 @@ def test_basic(self, values, cow): values = list(values) random.shuffle(values) size = len(values) - for value in values[:size//2]: + for value in values[:size // 2]: bitmap.add(value) expected_set.add(value) self.compare_with_set(bitmap, expected_set) - for value in values[size//2:]: + for value in values[size // 2:]: bitmap.add(value) with self.assertRaises(KeyError): bitmap.add_checked(value) expected_set.add(value) self.compare_with_set(bitmap, expected_set) - for value in values[:size//2]: + for value in values[:size // 2]: bitmap.remove(value) expected_set.remove(value) with self.assertRaises(KeyError): bitmap.remove(value) self.compare_with_set(bitmap, expected_set) - for value in values[size//2:]: + for value in values[size // 2:]: bitmap.discard(value) # check that we can discard element not in the bitmap bitmap.discard(value) @@ -203,9 +204,9 @@ def test_wrong_contain(self): @given(bitmap_cls) def test_wrong_constructor_values(self, cls): with self.assertRaises(TypeError): # this should fire a type error! - bitmap = cls([3, 'bla', 3, 42]) + cls([3, 'bla', 3, 42]) with self.assertRaises(ValueError): - bitmap = cls(range(0, 10, 0)) + cls(range(0, 10, 0)) @given(bitmap_cls, hyp_collection, st.booleans()) def test_to_array(self, cls, values, cow): @@ -240,7 +241,7 @@ def test_wrong_selection(self, cls, values, n, cow): with self.assertRaises(IndexError): bitmap[n + len(values)] with self.assertRaises(IndexError): - bitmap[-len(values)-1] + bitmap[-len(values) - 1] with self.assertRaises(IndexError): bitmap[-n - len(values) - 1] @@ -276,7 +277,7 @@ def test_slice_select_none(self, cls, values, start, stop, step, cow): def test_simple_rank(self, cls, values, cow): bitmap = cls(values, copy_on_write=cow) for i, value in enumerate(sorted(values)): - self.assertEqual(bitmap.rank(value), i+1) + self.assertEqual(bitmap.rank(value), i + 1) @given(bitmap_cls, hyp_collection, uint18, st.booleans()) def test_general_rank(self, cls, values, element, cow): @@ -295,7 +296,7 @@ def test_min(self, cls, values, cow): def test_wrong_min(self, cls): bitmap = cls() with self.assertRaises(ValueError): - m = bitmap.min() + bitmap.min() @given(bitmap_cls, hyp_collection, st.booleans()) def test_max(self, cls, values, cow): @@ -307,7 +308,7 @@ def test_max(self, cls, values, cow): def test_wrong_max(self, cls): bitmap = cls() with self.assertRaises(ValueError): - m = bitmap.max() + bitmap.max() @given(bitmap_cls, hyp_collection, uint32, st.booleans()) def test_next_set_bit(self, cls, values, other_value, cow): @@ -318,19 +319,19 @@ def test_next_set_bit(self, cls, values, other_value, cow): self.assertEqual(bitmap.next_set_bit(other_value), expected) except StopIteration: with self.assertRaises(ValueError): - b = bitmap.next_set_bit(other_value) + bitmap.next_set_bit(other_value) @given(bitmap_cls) def test_wrong_next_set_bit(self, cls): bitmap = cls() with self.assertRaises(ValueError): - b = bitmap.next_set_bit(0) + bitmap.next_set_bit(0) class BinaryOperationsTest(Util): @given(bitmap_cls, bitmap_cls, hyp_collection, hyp_collection, st.booleans()) - def test_binary_op(self, cls1, cls2, values1, values2, cow): + def test_binary_op(self, cls1, cls2, values1, values2, cow): for op in [operator.or_, operator.and_, operator.xor, operator.sub]: self.set1 = set(values1) self.set2 = set(values2) @@ -360,7 +361,6 @@ def test_binary_op_inplace(self, cls2, values1, values2, cow): self.assertEqual(self.bitmap2, old_bitmap2) self.compare_with_set(self.bitmap1, self.set1) - @given(bitmap_cls, hyp_collection, hyp_collection, st.booleans()) def test_binary_op_inplace_frozen(self, cls2, values1, values2, cow): for op in [operator.ior, operator.iand, operator.ixor, operator.isub]: @@ -417,13 +417,13 @@ def test_contains_range_arbitrary(self, cls, values, cow, start, end): def test_contains_range(self, cls, cow, start, end): assume(start < end) self.assertTrue(cls(range(start, end)).contains_range(start, end)) - self.assertTrue(cls(range(start, end)).contains_range(start, end-1)) - self.assertFalse(cls(range(start, end-1)).contains_range(start, end)) - self.assertTrue(cls(range(start, end)).contains_range(start+1, end)) - self.assertFalse(cls(range(start+1, end)).contains_range(start, end)) + self.assertTrue(cls(range(start, end)).contains_range(start, end - 1)) + self.assertFalse(cls(range(start, end - 1)).contains_range(start, end)) + self.assertTrue(cls(range(start, end)).contains_range(start + 1, end)) + self.assertFalse(cls(range(start + 1, end)).contains_range(start, end)) r = range(start, end) try: - middle = r[len(r)//2] # on 32bits systems, this call might fail when len(r) is too large + middle = r[len(r) // 2] # on 32bits systems, this call might fail when len(r) is too large except OverflowError: if sys.maxsize > 2**32: raise @@ -432,7 +432,7 @@ def test_contains_range(self, cls, cow, start, end): bm = cls(range(start, end)) - cls([middle]) self.assertFalse(bm.contains_range(start, end)) self.assertTrue(bm.contains_range(start, middle)) - self.assertTrue(bm.contains_range(middle+1, end)) + self.assertTrue(bm.contains_range(middle + 1, end)) @given(hyp_collection, st.booleans(), uint32, uint32) def test_add_remove_range(self, values, cow, start, end): @@ -447,12 +447,12 @@ def test_add_remove_range(self, values, cow, start, end): # Adding the range bm.add_range(start, end) self.assertTrue(bm.contains_range(start, end)) - self.assertEqual(bm.intersection_cardinality(BitMap(range(start, end), copy_on_write=cow)), end-start) + self.assertEqual(bm.intersection_cardinality(BitMap(range(start, end), copy_on_write=cow)), end - start) # Empty range (again) original = BitMap(bm) bm.remove_range(end, start) self.assertEqual(bm, original) - self.assertEqual(bm.intersection_cardinality(BitMap(range(start, end), copy_on_write=cow)), end-start) + self.assertEqual(bm.intersection_cardinality(BitMap(range(start, end), copy_on_write=cow)), end - start) # Removing the range bm.remove_range(start, end) self.assertFalse(bm.contains_range(start, end)) @@ -478,7 +478,7 @@ def test_cardinality(self, cls1, cls2, values1, values2, cow): (operator.or_, cls1.union_cardinality), (operator.and_, cls1.intersection_cardinality), (operator.sub, cls1.difference_cardinality), - (operator.xor, cls1.symmetric_difference_cardinality) + (operator.xor, cls1.symmetric_difference_cardinality), ]: self.bitmap1 = cls1(values1, copy_on_write=cow) self.bitmap2 = cls2(values2, copy_on_write=cow) @@ -501,7 +501,7 @@ def test_range_cardinality(self, cls, values, a, b): bm = cls(values) start, end = sorted([a, b]) - #make an intersection with the relevant range to test against + # make an intersection with the relevant range to test against test_bm = bm.intersection(BitMap(range(start, end))) self.assertEqual(len(test_bm), bm.range_cardinality(start, end)) @@ -516,7 +516,7 @@ def test_update(self, initial_values, all_values, cow): for values in all_values] self.initial_bitmap.update(*all_values) expected_result = functools.reduce( - lambda x, y: x | y, self.all_bitmaps+[self.initial_bitmap]) + lambda x, y: x | y, self.all_bitmaps + [self.initial_bitmap]) self.assertEqual(expected_result, self.initial_bitmap) self.assertEqual(type(expected_result), type(self.initial_bitmap)) @@ -527,7 +527,7 @@ def test_intersection_update(self, initial_values, all_values, cow): for values in all_values] self.initial_bitmap.intersection_update(*all_values) expected_result = functools.reduce( - lambda x, y: x & y, self.all_bitmaps+[self.initial_bitmap]) + lambda x, y: x & y, self.all_bitmaps + [self.initial_bitmap]) self.assertEqual(expected_result, self.initial_bitmap) self.assertEqual(type(expected_result), type(self.initial_bitmap)) @@ -591,18 +591,18 @@ def test_basic_properties(self, cls, values, cow): self.assertEqual(stats['n_values_array_containers'] + stats['n_values_bitset_containers'] + stats['n_values_run_containers'], len(bitmap)) self.assertEqual(stats['n_bytes_array_containers'], - 2*stats['n_values_array_containers']) + 2 * stats['n_values_array_containers']) self.assertEqual(stats['n_bytes_bitset_containers'], - 2**13*stats['n_bitset_containers']) + 2**13 * stats['n_bitset_containers']) if len(values) > 0: self.assertEqual(stats['min_value'], bitmap[0]) - self.assertEqual(stats['max_value'], bitmap[len(bitmap)-1]) + self.assertEqual(stats['max_value'], bitmap[len(bitmap) - 1]) self.assertEqual(stats['cardinality'], len(bitmap)) self.assertEqual(stats['sum_value'], sum(values)) @given(bitmap_cls) def test_implementation_properties_array(self, cls): - values = range(2**16-10, 2**16+10, 2) + values = range(2**16 - 10, 2**16 + 10, 2) stats = cls(values).get_statistics() self.assertEqual(stats['n_array_containers'], 2) self.assertEqual(stats['n_bitset_containers'], 0) @@ -697,7 +697,7 @@ def test_shift(self, cls, values, offset, cow): bm_copy = cls(bm_before) bm_after = bm_before.shift(offset) self.assertEqual(bm_before, bm_copy) - expected = cls([val+offset for val in values if val+offset in range(0, 2**32)], copy_on_write=cow) + expected = cls([val + offset for val in values if val + offset in range(0, 2**32)], copy_on_write=cow) self.assertEqual(bm_after, expected) @@ -720,7 +720,7 @@ def test_incompatible_xor(self): self.incompatible_op(lambda x, y: x ^ y) def test_incompatible_sub(self): - self.incompatible_op(lambda x, y: x-y) + self.incompatible_op(lambda x, y: x - y) def test_incompatible_or_inplace(self): self.incompatible_op(lambda x, y: x.__ior__(y)) @@ -819,7 +819,7 @@ def test_immutability(self, values, other, number): with self.assertRaises(AttributeError): frozen.symmetric_difference_update(other) with self.assertRaises(AttributeError): - frozen.update(number, number+10) + frozen.update(number, number + 10) with self.assertRaises(AttributeError): frozen.overwrite(other) self.assertEqual(frozen, copy) @@ -892,8 +892,11 @@ def test_shrink_to_fit(self, cls): bm3 = cls(bm1, optimize=True) self.assertEqual(bm3.shrink_to_fit(), 0) + small_integer = st.integers(min_value=0, max_value=200) small_integer_list = st.lists(min_size=0, max_size=2000, elements=small_integer) + + class PythonSetEquivalentTest(unittest.TestCase): """ The main goal of this class is to make sure the BitMap api is a superset of the python builtin set api. @@ -933,7 +936,6 @@ def test_convert_to_set(self, BitMapClass, list1, cow): for i in range(min_value, max_value): self.assertEqual(i in s1, i in converted_set) - @given(bitmap_cls, small_integer_list, small_integer_list, st.booleans()) def test_difference(self, BitMapClass, list1, list2, cow): if BitMapClass == BitMap: @@ -1010,7 +1012,6 @@ def test_issubset(self, BitMapClass, list1, list2, cow): self.assertEqual(s1.issubset(s2), b1.issubset(b2)) self.assertEqual(SetClass.issubset(s1, s2), BitMapClass.issubset(b1, b2)) - @given(bitmap_cls, small_integer_list, small_integer_list, st.booleans()) def test_le(self, BitMapClass, list1, list2, cow): if BitMapClass == BitMap: @@ -1030,7 +1031,6 @@ def test_le(self, BitMapClass, list1, list2, cow): self.assertEqual(SetClass.__le__(s1, s2), BitMapClass.__le__(b1, b2)) self.assertEqual((s1 <= s2), (b1 <= b2)) - @given(bitmap_cls, small_integer_list, small_integer_list, st.booleans()) def test_ge(self, BitMapClass, list1, list2, cow): if BitMapClass == BitMap: @@ -1068,7 +1068,6 @@ def test_eq(self, BitMapClass, list1, list2, cow): self.assertEqual(SetClass.__eq__(s1, s2), BitMapClass.__eq__(b1, b2)) self.assertEqual((s1 == s2), (b1 == b2)) - @given(bitmap_cls, small_integer_list, small_integer_list, st.booleans()) def test_issuperset(self, BitMapClass, list1, list2, cow): if BitMapClass == BitMap: @@ -1105,8 +1104,7 @@ def test_isdisjoint(self, BitMapClass, list1, list2, cow): self.assertEqual(s1.isdisjoint(s2), b1.isdisjoint(b2)) self.assertEqual(SetClass.isdisjoint(s1, s2), BitMapClass.isdisjoint(b1, b2)) - - @given(small_integer_list, st.booleans()) + @given(small_integer_list, st.booleans()) def test_clear(self, list1, cow): b1 = BitMap(list1, copy_on_write=cow) b1.clear() @@ -1118,8 +1116,8 @@ def test_pop(self, list1, cow): starting_length = len(b1) if starting_length >= 1: popped_element = b1.pop() - self.assertEqual(len(b1), starting_length - 1) #length decreased by one - self.assertFalse(popped_element in b1) #and element isn't in the BitMap anymore + self.assertEqual(len(b1), starting_length - 1) # length decreased by one + self.assertFalse(popped_element in b1) # and element isn't in the BitMap anymore else: with self.assertRaises(KeyError): b1.pop() @@ -1130,14 +1128,13 @@ def test_copy(self, BitMapClass, list1, cow): b2 = b1.copy() self.assertEqual(b2, b1) - @given(small_integer_list, st.booleans()) def test_copy_writable(self, list1, cow): b1 = BitMap(list1, copy_on_write=cow) b2 = b1.copy() try: - new_element = max(b1) + 1 #doesn't exist in the set + new_element = max(b1) + 1 # doesn't exist in the set except ValueError: new_element = 1 @@ -1155,7 +1152,7 @@ def test_overwrite(self, BitMapClass, list1, list2, cow): orig2 = b2.copy() b1.overwrite(b2) self.assertEqual(b1, b2) # the two bitmaps are now equal - self.assertNotEqual(b1, orig1) # the first bitmap has been modified + self.assertNotEqual(b1, orig1) # the first bitmap has been modified self.assertEqual(b2, orig2) # the second bitmap was left untouched with self.assertRaises(ValueError): b1.overwrite(b1) @@ -1184,7 +1181,6 @@ def test_symmetric_difference_update(self, list1, list2, cow): self.assertEqual(s1, set(b1)) - @given(bitmap_cls, small_integer_list, small_integer_list, st.booleans()) def test_dunder(self, BitMapClass, list1, list2, cow): """ @@ -1247,7 +1243,7 @@ def test_remove(self, list1, value, cow): b1_raised = True self.assertEqual(s1, set(b1)) - self.assertEqual(s1_raised, b1_raised) #Either both raised exception or neither did + self.assertEqual(s1_raised, b1_raised) # Either both raised exception or neither did @given(bitmap_cls, small_integer_list, small_integer_list, small_integer_list, st.booleans()) def test_nary_union(self, BitMapClass, list1, list2, list3, cow): @@ -1323,7 +1319,6 @@ def test_nary_intersection_update(self, list1, list2, list3, cow): BitMap.intersection_update(b1, b2, b3) self.assertEqual(s1, set(b1)) - s1 = set(list1) s2 = set(list2) s3 = set(list3) @@ -1337,7 +1332,6 @@ def test_nary_intersection_update(self, list1, list2, list3, cow): self.assertEqual(s1, set(b1)) - @given(small_integer_list, small_integer_list, small_integer_list, st.booleans()) def test_nary_difference_update(self, list1, list2, list3, cow): s1 = set(list1) @@ -1352,7 +1346,6 @@ def test_nary_difference_update(self, list1, list2, list3, cow): BitMap.difference_update(b1, b2, b3) self.assertEqual(s1, set(b1)) - s1 = set(list1) s2 = set(list2) s3 = set(list3) @@ -1380,7 +1373,6 @@ def test_nary_update(self, list1, list2, list3, cow): BitMap.update(b1, b2, b3) self.assertEqual(s1, set(b1)) - s1 = set(list1) s2 = set(list2) s3 = set(list3) @@ -1394,13 +1386,16 @@ def test_nary_update(self, list1, list2, list3, cow): self.assertEqual(s1, set(b1)) + small_list_of_uin32 = st.lists(min_size=0, max_size=400, elements=uint32) large_list_of_uin32 = st.lists(min_size=600, max_size=1000, elements=uint32, unique=True) + + class StringTest(unittest.TestCase): @given(bitmap_cls, small_list_of_uin32) def test_small_list(self, cls, collection): - #test that repr for a small bitmap is equal to the original bitmap + # test that repr for a small bitmap is equal to the original bitmap bm = cls(collection) self.assertEqual(bm, eval(repr(bm))) @@ -1436,8 +1431,8 @@ def assert_regex(self, pattern, text): self.fail('Regex "%s" does not match text "%s".' % (pattern, text)) def test_version(self): - self.assert_regex('\d+\.\d+\.\d+(?:\.dev\d+)?', pyroaring.__version__) - self.assert_regex('v\d+\.\d+\.\d+', pyroaring.__croaring_version__) + self.assert_regex(r'\d+\.\d+\.\d+(?:\.dev\d+)?', pyroaring.__version__) + self.assert_regex(r'v\d+\.\d+\.\d+', pyroaring.__croaring_version__) if __name__ == "__main__": diff --git a/tox.ini b/tox.ini index 77fea8e..18c4519 100644 --- a/tox.ini +++ b/tox.ini @@ -54,3 +54,12 @@ commands = python cydoctest.py +[testenv:linting] +deps = + flake8 + flake8-isort + flake8-noqa +skip_sdist = true +skip_install = true +commands = + flake8