diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 1f33c8f..ede3a91 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -23,10 +23,7 @@ jobs: python-version: ${{ matrix.python }} - name: Install dependencies - run: pip install . - - - name: Install Mypy - run: pip install mypy + run: pip install -e '.[test]' - name: Static analysis run: mypy ./src diff --git a/pyproject.toml b/pyproject.toml index f008b26..222dea4 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -3,7 +3,7 @@ requires = ["setuptools >= 61.0"] build-backend = "setuptools.build_meta" [project] -name = "PyBloomer" +name = "OkBloomer" version = "0.0.1" requires-python = ">= 3.10" dependencies = [ @@ -12,10 +12,14 @@ dependencies = [ authors = [ {name = "Andrew DalPino", email = "support@andrewdalpino.com"}, ] -description = "PyBloomer is an implementation of the OkBloomer algorithm, an autoscaling Bloom filter with ultra-low memory footprint for Python." +description = "PyBloomer is an Python implementation of the OkBloomer algorithm, an autoscaling Bloom filter with ultra-low memory footprint." readme = "README.md" license = {text = "MIT"} +[project.optional-dependencies] +dev = ["mypy"] +test = ["mypy"] + [project.urls] Homepage = "https://github.com/andrewdalpino/PyBloomer" Documentation = "https://github.com/andrewdalpino/PyBloomer/README.md" diff --git a/tests/test_bloom_filter.py b/tests/test_bloom_filter.py index 0c4b22b..920cf92 100644 --- a/tests/test_bloom_filter.py +++ b/tests/test_bloom_filter.py @@ -1,14 +1,12 @@ import unittest +import random +import string import pybloomer class TestBloomFilter(unittest.TestCase): def test_basic(self): - filter = pybloomer.BloomFilter( - max_false_positive_rate=0.01, - num_hashes=4, - layer_size=32000000, - ) + filter = pybloomer.BloomFilter() self.assertEqual(filter.false_positive_rate, 0) @@ -26,12 +24,10 @@ def test_basic(self): self.assertTrue(filter.exists('bar')) self.assertGreater(filter.false_positive_rate, 0) + self.assertFalse(filter.exists('baz')) + def test_exists_or_insert(self): - filter = pybloomer.BloomFilter( - max_false_positive_rate=0.01, - num_hashes=4, - layer_size=32000000, - ) + filter = pybloomer.BloomFilter() self.assertFalse(filter.exists_or_insert('foo')) @@ -43,4 +39,30 @@ def test_exists_or_insert(self): self.assertFalse(filter.exists_or_insert('baz')) - self.assertTrue(filter.exists_or_insert('baz')) \ No newline at end of file + self.assertTrue(filter.exists_or_insert('baz')) + + def test_autoscaling(self): + random.seed(0) + + filter = pybloomer.BloomFilter( + max_false_positive_rate=0.01, + num_hashes=4, + layer_size=320000, + ) + + self.assertEqual(filter.num_layers, 1) + + filter.insert('foo') + + for i in range(0, 100000): + filter.insert(''.join(random.choice(string.ascii_letters) for j in range(20))) + + filter.insert('bar') + + self.assertEqual(filter.num_layers, 3) + self.assertLessEqual(filter.false_positive_rate, 0.01) + self.assertLessEqual(filter.utilization, 1.0) + + self.assertTrue(filter.exists('foo')) + self.assertTrue(filter.exists('bar')) + self.assertFalse(filter.exists('father'))