From c2545f4ec9369109dec5c65d2fb449a4f99b87c1 Mon Sep 17 00:00:00 2001 From: Thomas A Caswell Date: Mon, 16 Dec 2024 15:53:08 -0500 Subject: [PATCH 1/5] TST: switch to using a fixture rather than a global for test object --- test_history.py | 135 +++++++++++++++++++++++------------------------- 1 file changed, 64 insertions(+), 71 deletions(-) diff --git a/test_history.py b/test_history.py index 6a291d6..7ac75da 100644 --- a/test_history.py +++ b/test_history.py @@ -1,25 +1,24 @@ -import tempfile from historydict import HistoryDict import pytest + OBJ_ID_LEN = 36 -h = None -def setup(): - global h - h = HistoryDict(':memory:') +@pytest.fixture +def h(): + return HistoryDict(":memory:") -def test_historydict(): - run_id = ''.join(['a'] * OBJ_ID_LEN) +def test_historydict(h): + run_id = "".join(["a"] * OBJ_ID_LEN) # Simple round-trip: put and past - config1 = {'plot_x': 'long', 'plot_y': 'island'} + config1 = {"plot_x": "long", "plot_y": "island"} h._put(run_id, config1) result1 = h.past(run_id) assert result1 == config1 # Put a second entry. Check that past returns most recent. - config2 = {'plot_x': 'new', 'plot_y': 'york'} + config2 = {"plot_x": "new", "plot_y": "york"} h._put(run_id, config2) result2 = h.past(run_id) assert result2 == config2 @@ -28,102 +27,95 @@ def test_historydict(): assert result1 == config1 -def test_clear(): - h._put('hi', 'mom') +def test_clear(h): + h._put("hi", "mom") h.clear() with pytest.raises(KeyError): - h.past('hi') + h.past("hi") -def test_trim(): +def test_trim(h): with pytest.raises(NotImplementedError): h.trim() -def test_neg_numback_fails(): +def test_neg_numback_fails(h): with pytest.raises(ValueError): - h.past('test', -1) + h.past("test", -1) -def test_nonexistent_past_fails(): - h['cats'] = 123 +def test_nonexistent_past_fails(h): + h["cats"] = 123 with pytest.raises(ValueError): - h.past('cats', 1) - h['cats'] = 456 - h.past('cats', 1) # should not raise + h.past("cats", 1) + h["cats"] = 456 + h.past("cats", 1) # should not raise -def test_gs_items(): - h[123] = 'aardvark' - assert h[123] == 'aardvark' +def test_gs_items(h): + h[123] = "aardvark" + assert h[123] == "aardvark" -def test_opening(): - with tempfile.NamedTemporaryFile(delete=False) as fn: - filename = fn.name +def test_opening(tmp_path): + filename = tmp_path / "test" h1 = HistoryDict(filename) - h1['aardvark'] = 'ants' + h1["aardvark"] = "ants" del h1 h2 = HistoryDict(filename) - assert h2['aardvark'] == 'ants' + assert h2["aardvark"] == "ants" -def test_iter(): - h.clear() - keys = set('abcd') +def test_iter(h): + keys = set("abcd") for k in keys: h[k] = k for k, v in h.items(): assert k == v -def test_del(): - h.clear() - h['a'] = 123 - h['a'] = 456 - assert 'a' in h - del h['a'] - assert 'a' not in h +def test_del(h): + h["a"] = 123 + h["a"] = 456 + assert "a" in h + del h["a"] + assert "a" not in h # Add a value back to check that all old values were cleared. - h['a'] = 789 + h["a"] = 789 with pytest.raises(ValueError): - h.past('a', 1) - assert h['a'] == 789 - assert h.past('a', 0) == 789 + h.past("a", 1) + assert h["a"] == 789 + assert h.past("a", 0) == 789 -def test_no_key_in_del(): - h.clear() +def test_no_key_in_del(h): with pytest.raises(KeyError): - del h['aardvark'] + del h["aardvark"] -def test_len(): - h.clear() - keys = set('abcd') +def test_len(h): + keys = set("abcd") for k in keys: h[k] = k assert len(keys) == len(h) -def test_get(): - h.clear() - b = h.get('b', 'aardvark') - assert b, 'aardvark' +def test_get(h): + b = h.get("b", "aardvark") + assert b, "aardvark" -def test_protected_key(): +def test_protected_key(h): with pytest.raises(ValueError): h[HistoryDict.RESERVED_KEY_KEY] with pytest.raises(ValueError): - h[HistoryDict.RESERVED_KEY_KEY] = 'aardvark' + h[HistoryDict.RESERVED_KEY_KEY] = "aardvark" -def test_repr(): - h.clear() - kvpairs = (('foo', 'bar'), ('spam', 'spam spam spam')) +def test_repr(h): + kvpairs = (("foo", "bar"), ("spam", "spam spam spam")) dct = {} for k, v in kvpairs: dct[k] = v @@ -131,17 +123,18 @@ def test_repr(): assert repr(dict(h)) == repr(h) assert dict(h) == dct -def test_flush(): - with tempfile.NamedTemporaryFile(delete=False) as fn: - # Needed for windows compatibility - g = HistoryDict(fn.name) - g['k'] = {'a': 1} - g['k']['a'] = 2 - # Check that mutated value persists. - del g - g = HistoryDict(fn.name) - assert g['k']['a'] == 2 - - # finally smoke test the API - g.flush() - g._flush('k') + +def test_flush(tmp_path): + pth = tmp_path / "test.db" + # Needed for windows compatibility + g = HistoryDict(pth) + g["k"] = {"a": 1} + g["k"]["a"] = 2 + # Check that mutated value persists. + del g + g = HistoryDict(pth) + assert g["k"]["a"] == 2 + + # finally smoke test the API + g.flush() + g._flush("k") From 5f84ea409a8b4266a7e56882dd3abc398a2ce698 Mon Sep 17 00:00:00 2001 From: Thomas A Caswell Date: Mon, 16 Dec 2024 15:53:32 -0500 Subject: [PATCH 2/5] CI: update supported Python range --- .github/workflows/testing.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/testing.yml b/.github/workflows/testing.yml index e47d43c..e44047a 100644 --- a/.github/workflows/testing.yml +++ b/.github/workflows/testing.yml @@ -14,7 +14,7 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - python-version: ["3.8", "3.9", "3.10", "3.11"] + python-version: ["3.9", "3.10", "3.11", "3.12", "3.13"] fail-fast: false defaults: From d9996b5a8e8fd701fb6bbed2b36e6142d78d8f91 Mon Sep 17 00:00:00 2001 From: Thomas A Caswell Date: Mon, 16 Dec 2024 15:54:48 -0500 Subject: [PATCH 3/5] MNT: version bump + add Python classifiers --- setup.py | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/setup.py b/setup.py index 548064e..d85285a 100644 --- a/setup.py +++ b/setup.py @@ -1,11 +1,18 @@ from setuptools import setup setup(name='historydict', - version='1.2.6', + version='1.2.7', author='Brookhaven National Laboratory', py_modules=['historydict'], description='A persistent dictionary with history backed by sqlite', url='http://github.com/Nikea/historydict', platforms='Cross platform (Linux, Mac OSX, Windows)', license_files=('LICENSE.',), + classifiers = [ + "Programming Language :: Python :: 3.9", + "Programming Language :: Python :: 3.10", + "Programming Language :: Python :: 3.11", + "Programming Language :: Python :: 3.12", + "Programming Language :: Python :: 3.13", + ] ) From ad34350ddbb5ad16a22d62a53f556c61f3ed18da Mon Sep 17 00:00:00 2001 From: Thomas A Caswell Date: Mon, 16 Dec 2024 16:00:05 -0500 Subject: [PATCH 4/5] MNT: try adding install requires --- setup.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/setup.py b/setup.py index d85285a..b617ea1 100644 --- a/setup.py +++ b/setup.py @@ -14,5 +14,6 @@ "Programming Language :: Python :: 3.11", "Programming Language :: Python :: 3.12", "Programming Language :: Python :: 3.13", - ] + ], + install_requires=['setuptools'], ) From 1a1a27c00cea9c54c1d67c2ef2c5c4c3bf68ee8c Mon Sep 17 00:00:00 2001 From: Thomas A Caswell Date: Mon, 16 Dec 2024 16:46:07 -0500 Subject: [PATCH 5/5] CI: don't invoke setup.py directly --- .github/workflows/testing.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/testing.yml b/.github/workflows/testing.yml index e44047a..8aa7346 100644 --- a/.github/workflows/testing.yml +++ b/.github/workflows/testing.yml @@ -35,6 +35,6 @@ jobs: set -vxeuo pipefail pip install pytest pytest-cov - python setup.py install + pip install -v . py.test --cov=historydict --cov-report term-missing