diff --git a/.github/workflows/testing.yml b/.github/workflows/testing.yml index e47d43c..8aa7346 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: @@ -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 diff --git a/setup.py b/setup.py index 548064e..b617ea1 100644 --- a/setup.py +++ b/setup.py @@ -1,11 +1,19 @@ 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", + ], + install_requires=['setuptools'], ) 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")