Skip to content

Commit 1c23ef5

Browse files
committed
Refactor cache and add tests for it.
No longer inheirts from dict, that was kinda whack.
1 parent 7fb4973 commit 1c23ef5

File tree

2 files changed

+73
-21
lines changed

2 files changed

+73
-21
lines changed

screen_brightness_control/helpers.py

Lines changed: 20 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
from abc import ABC, abstractclassmethod
1212
from dataclasses import dataclass, field
1313
from functools import lru_cache
14-
from typing import Callable, List, Optional, Tuple, Union
14+
from typing import Any, Callable, Dict, List, Optional, Tuple, Union
1515

1616
from .exceptions import (EDIDParseError, MaxRetriesExceededError, # noqa:F401
1717
ScreenBrightnessError, format_exc)
@@ -185,46 +185,45 @@ def _gdi(cls) -> List[dict]:
185185
...
186186

187187

188-
class __Cache(dict):
188+
class __Cache:
189189
'''class to cache data with a short shelf life'''
190190

191191
def __init__(self):
192+
self.logger = logger.getChild(f'{self.__class__.__name__}_{id(self)}')
192193
self.enabled = True
193-
super().__init__()
194+
self._store: Dict[str, Tuple[Any, float]] = {}
194195

195-
def get(self, key, *args, **kwargs):
196+
def get(self, key):
196197
if not self.enabled:
197198
return None
198199

199200
try:
200-
value, expires, orig_args, orig_kwargs = self[key]
201+
value, expires = self._store[key]
201202
if time.time() < expires:
202-
if orig_args == args and orig_kwargs == kwargs:
203-
logger.debug(f'cache get {repr(key)}')
204-
return value
205-
else:
206-
logger.debug(f'cache get {repr(key)} = [expired]')
207-
del self[key]
203+
self.logger.debug(f'cache get {repr(key)}')
204+
return value
205+
self.logger.debug(f'cache get {repr(key)} = [expired]')
206+
del self._store[key]
208207
except KeyError:
209-
logger.debug(f'cache get {repr(key)} = [KeyError]')
210-
pass
208+
self.logger.debug(f'cache get {repr(key)} = [KeyError]')
209+
return None
211210

212-
def store(self, key, value, *args, expires=1, **kwargs):
213-
self[key] = (value, expires + time.time(), args, kwargs)
214-
logger.debug(f'cache set {repr(key)}, expires={expires}')
211+
def store(self, key, value, expires=1):
212+
self.logger.debug(f'cache set {repr(key)}, expires={expires}')
213+
self._store[key] = (value, expires + time.time())
215214

216215
def expire(self, key=None, startswith=None):
217216
if key is not None:
218217
try:
219-
del self[key]
220-
logger.debug(f'cache expire key {repr(key)}')
218+
del self._store[key]
219+
self.logger.debug(f'cache expire key {repr(key)}')
221220
except KeyError:
222221
pass
223222
elif startswith is not None:
224-
for i in tuple(self.keys()):
223+
for i in tuple(self._store.keys()):
225224
if i.startswith(startswith):
226-
del self[i]
227-
logger.debug(f'cache expire key {repr(i)}')
225+
del self._store[i]
226+
self.logger.debug(f'cache expire key {repr(i)}')
228227

229228

230229
@dataclass

tests/test_helpers.py

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
'''
55
import os
66
import sys
7+
import time
78
import unittest
89
from timeit import timeit
910

@@ -12,6 +13,58 @@
1213

1314
sys.path.insert(0, os.path.abspath('./'))
1415
import screen_brightness_control as sbc # noqa: E402
16+
# for the cache tests. Refs to __Cache get scrambled within classes
17+
from screen_brightness_control.helpers import __Cache as _Cache
18+
19+
20+
class TestCache(unittest.TestCase):
21+
cache: _Cache
22+
23+
def setUp(self):
24+
super().setUp()
25+
self.cache = _Cache()
26+
27+
def test_get(self):
28+
c_time = time.time()
29+
self.cache._store.update({
30+
'a': (123, c_time + 1),
31+
'b': (456, c_time - 1)
32+
})
33+
34+
self.assertEqual(self.cache.get('a'), 123)
35+
self.assertIn('a', self.cache._store)
36+
self.assertEqual(self.cache.get('b'), None)
37+
# key should have been deleted as expired
38+
self.assertNotIn('b', self.cache._store)
39+
40+
def test_store(self, expires=1):
41+
c_time = time.time()
42+
self.cache.store('abc', 123, expires=expires)
43+
self.assertIn('abc', self.cache._store)
44+
item = self.cache._store['abc']
45+
self.assertEqual(item[0], 123)
46+
self.assertLess((c_time + expires) - item[1], 0.1)
47+
48+
def test_store_expires(self):
49+
self.test_store(3)
50+
self.test_store(5)
51+
self.test_store(-1)
52+
53+
def test_expire(self):
54+
self.cache._store.update({
55+
'a': (123, 0),
56+
'b': (123, 0),
57+
'bc': (123, 0),
58+
'def': (123, 0)
59+
})
60+
self.cache.expire('a')
61+
self.assertNotIn('a', self.cache._store)
62+
self.cache.expire(startswith='b')
63+
self.assertNotIn('b', self.cache._store)
64+
self.assertNotIn('bc', self.cache._store)
65+
66+
self.assertIn('def', self.cache._store)
67+
1568

1669

1770
class TestDisplay(TestCase):

0 commit comments

Comments
 (0)