PK#!LHc€†™sandpiper/util.pyimport unittest from .cache import Cache class StandardTests(unittest.TestCase): def get_driver(self): return None def ready_driver(self): pass def kill_driver(self): pass def setUp(self): self.driver = self.get_driver() self.ready_driver() if not self.driver: raise unittest.SkipTest('The driver is not defined.') self.cache = Cache(self.driver) def tearDown(self): self.kill_driver() del self.cache del self.driver def test_set_and_get(self): self.cache.set('panda', 'something') self.assertEqual('something', self.cache.get('panda')) def test_set_twice(self): self.cache.set('panda', 'something') self.assertEqual('something', self.cache.get('panda')) self.cache.set('panda', 'python') self.assertEqual('python', self.cache.get('panda')) def test_get_nothing(self): self.assertEqual(None, self.cache.get('panda')) def test_remove_once(self): self.cache.set('panda', 'something') self.cache.remove('panda') self.assertEqual(None, self.cache.get('panda')) def test_remove_once(self): self.cache.set('panda', 'something') self.cache.remove('panda') self.cache.remove('panda') # ensure that there is no error. self.assertEqual(None, self.cache.get('panda')) def test_dictionary_access(self): self.cache['panda'] = 'something' self.assertEqual('something', self.cache['panda']) PKæLH:7Ösandpiper/__init__.pyfrom .cache import Cache PKóLHDBÑ4°°sandpiper/cache.pyfrom .adapter import InMemory from .mixin import DictionaryAccess class Cache(DictionaryAccess): def __init__(self, driver=InMemory()): self.driver = driver def get(self, key): return self.driver.get(key) def set(self, key, value): self.driver.set(key, value) def remove(self, key): self.driver.remove(key) def find(self, pattern): return self.driver.find(pattern) PKç!LH‡R&´ÜÜsandpiper/mixin.pyclass DictionaryAccess(object): def __getitem__(self, key): return self.get(key) def __setitem__(self, key, value): self.set(key, value) def __delitem__(self, key): self.remove(key) PKˆLHëkV£sandpiper/adapter/abstract.pyclass Abstract(object): def get(self, key): raise NotImplementedError() def set(self, key, value): raise NotImplementedError() def remove(self, key): raise NotImplementedError() def find(self, pattern): raise NotImplementedError() PK},LHÆOØ|­­sandpiper/adapter/dynamodb.pyimport decimal import json from .abstract import Abstract class DynamoDB(object): def __init__(self, storage, namespace = 'default'): self._namespace = namespace self._storage = storage def get(self, key): response = self._table().get_item(Key = {'key': key}) item = response['Item'] if 'Item' in response else None return item['value'] if item else None def set(self, key, value): self._table().put_item(Item = self._prepare_for_setter({ 'key': key, 'value': value, })) def remove(self, key): self._table().delete_item(Key = {'key': key}) def _table_name(self): return 'sandpiper.cache.{}'.format(self._namespace) def _table(self): return self._storage.Table(self._table_name()) def _prepare_for_setter(self, data): return self._decode(json.dumps(data)) def _decode(self, data): return json.loads(data, parse_float = decimal.Decimal) def prepare(self, **kwargs): throughput = { 'ReadCapacityUnits': kwargs['io_read'] if 'io_read' in kwargs else 5, 'WriteCapacityUnits': kwargs['io_write'] if 'io_write' in kwargs else 4, } self._storage.create_table( TableName = self._table_name(), KeySchema = [ { 'AttributeName': 'key', 'KeyType': 'HASH' } ], AttributeDefinitions = [ { 'AttributeName': 'key', 'AttributeType': 'S' } ], ProvisionedThroughput = throughput ) PKð LHx¢o¡>>sandpiper/adapter/__init__.pyfrom .dynamodb import DynamoDB from .inmemory import InMemory PK”LHÄQ[E´´sandpiper/adapter/inmemory.pyfrom .abstract import Abstract class InMemory(object): def __init__(self, storage=None): self._storage = storage or {} def get(self, key): if key not in self._storage: return None return self._storage[key] def set(self, key, value): self._storage[key] = value def remove(self, key): if key not in self._storage: return del self._storage[key] PK1LH^-Ò )sandpiper-0.1.0.dist-info/DESCRIPTION.rstUNKNOWN PK1LH‚—yææ'sandpiper-0.1.0.dist-info/metadata.json{"classifiers": ["Development Status :: 5 - Production/Stable", "Intended Audience :: Developers", "License :: OSI Approved :: MIT License", "Operating System :: OS Independent", "Programming Language :: Python", "Programming Language :: Python :: 3", "Topic :: Software Development :: Libraries"], "extensions": {"python.details": {"contacts": [{"email": "juti_n@yahoo.co.jp", "name": "Juti Noppornpitak", "role": "author"}], "document_names": {"description": "DESCRIPTION.rst"}, "project_urls": {"Home": "https://github.com/shiroyuki/sandpiper"}}}, "generator": "bdist_wheel (0.26.0)", "license": "MIT", "metadata_version": "2.0", "name": "sandpiper", "summary": "A Generic/Extendible Key-value Store Interface Library", "version": "0.1.0"}PK1LHµZ‹H 'sandpiper-0.1.0.dist-info/top_level.txtsandpiper PK1LH}À‚¼\\sandpiper-0.1.0.dist-info/WHEELWheel-Version: 1.0 Generator: bdist_wheel (0.26.0) Root-Is-Purelib: true Tag: py3-none-any PK1LH‰èæ>dd"sandpiper-0.1.0.dist-info/METADATAMetadata-Version: 2.0 Name: sandpiper Version: 0.1.0 Summary: A Generic/Extendible Key-value Store Interface Library Home-page: https://github.com/shiroyuki/sandpiper Author: Juti Noppornpitak Author-email: juti_n@yahoo.co.jp License: MIT Platform: UNKNOWN Classifier: Development Status :: 5 - Production/Stable Classifier: Intended Audience :: Developers Classifier: License :: OSI Approved :: MIT License Classifier: Operating System :: OS Independent Classifier: Programming Language :: Python Classifier: Programming Language :: Python :: 3 Classifier: Topic :: Software Development :: Libraries UNKNOWN PK1LHÓ¹aÏ|| sandpiper-0.1.0.dist-info/RECORDsandpiper/__init__.py,sha256=MC9HH1xvF0YMmvlW-DMLAdyG1upTYL511R5IZ072WoI,25 sandpiper/cache.py,sha256=MjgkzChNzVlgPJUWcKv1uEKJIvT3cBycAX9Aer0K-aI,432 sandpiper/mixin.py,sha256=V-MqR6VNw98TFjNQ8yOQ9MTiq0yMP91cDufJDN59cJ4,220 sandpiper/util.py,sha256=hO6He7bfTDDhN4MkI1nZY3AcMJRwNM1P01l02iwQ6to,1558 sandpiper/adapter/__init__.py,sha256=MpKJPsFwOaC6ufDOdcZWpyIvd8P0iy2o4M9eK0LoysA,62 sandpiper/adapter/abstract.py,sha256=cQg5wkPFZ29P9NApUhOqQjXCQywm10lM9pIcV_VrDrQ,282 sandpiper/adapter/dynamodb.py,sha256=w7gTKJt3pKc6oUwWl0VZ4jodaIX-qer-QGhwyVo0hfQ,1709 sandpiper/adapter/inmemory.py,sha256=B3_woJ6K5frakHuqyfmDFGpA8X2gTF9vQ3R3lKSsGUE,436 sandpiper-0.1.0.dist-info/DESCRIPTION.rst,sha256=OCTuuN6LcWulhHS3d5rfjdsQtW22n7HENFRh6jC6ego,10 sandpiper-0.1.0.dist-info/METADATA,sha256=crdZkCw51HxnMFzSVIAckwrvS2BJqJPYvWjCNNNlFjc,612 sandpiper-0.1.0.dist-info/RECORD,, sandpiper-0.1.0.dist-info/WHEEL,sha256=zX7PHtH_7K-lEzyK75et0UBa3Bj8egCBMXe1M4gc6SU,92 sandpiper-0.1.0.dist-info/metadata.json,sha256=L3BwGXSwlOKrMtQOont25dC65DcVXXMvk_37AIM2zxo,742 sandpiper-0.1.0.dist-info/top_level.txt,sha256=fpXsErbRBrxn1zW4_5cH9RmqV1r0ZYE_QuwbQo1YJeg,10 PK#!LHc€†™sandpiper/util.pyPKæLH:7ÖEsandpiper/__init__.pyPKóLHDBÑ4°°‘sandpiper/cache.pyPKç!LH‡R&´ÜÜqsandpiper/mixin.pyPKˆLHëkV£} sandpiper/adapter/abstract.pyPK},LHÆOØ|­­Ò sandpiper/adapter/dynamodb.pyPKð LHx¢o¡>>ºsandpiper/adapter/__init__.pyPK”LHÄQ[E´´3sandpiper/adapter/inmemory.pyPK1LH^-Ò )"sandpiper-0.1.0.dist-info/DESCRIPTION.rstPK1LH‚—yææ'ssandpiper-0.1.0.dist-info/metadata.jsonPK1LHµZ‹H 'žsandpiper-0.1.0.dist-info/top_level.txtPK1LH}À‚¼\\ísandpiper-0.1.0.dist-info/WHEELPK1LH‰èæ>dd"†sandpiper-0.1.0.dist-info/METADATAPK1LHÓ¹aÏ|| *sandpiper-0.1.0.dist-info/RECORDPKä