Skip to content

Commit

Permalink
basic rings and storage
Browse files Browse the repository at this point in the history
  • Loading branch information
youknowone committed Aug 9, 2016
1 parent 55fb267 commit 2026320
Show file tree
Hide file tree
Showing 6 changed files with 135 additions and 0 deletions.
14 changes: 14 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@

dist
.env
*.pyc
*.egg-info
MANIFEST

.cache
.eggs
.idea
.tox
.ropeproject
/build
setup.cfg
Empty file added cachain/__init__.py
Empty file.
73 changes: 73 additions & 0 deletions cachain/ingredient.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@


class Key(object):

def __init__(self, key):
self.key = key

def build(self, args):
raise NotImplementedError


class FormatKey(Key):

def build(self, args):
return self.key.format(**args)


class CallableKey(Key):

def build(self, args):
return self.key(**args)


class Ring(object):

def __init__(self, storage, key):
self.storage = storage
if not isinstance(key, Key):
if isinstance(key, (str, unicode)):
key = FormatKey(key)
elif callable(key):
key = CallableKey(key)
else:
raise TypeError
self.key = key

@staticmethod
def _key_args(args, kwargs):
if args and kwargs:
raise TypeError
if args and len(args) > 1:
raise TypeError
if args:
key = args[0]
else:
key = kwargs
return key

def get(self, *args, **kwargs):
key_args = self._key_args(args, kwargs)
return self.get_by_key(key_args)

def get_by_key(self, key_args):
built_key = self.key.build(key_args)
return self.storage.get(built_key)

def set(self, _value, *args, **kwargs):
key_args = self._key_args(args, kwargs)
if callable(_value):
_value = _value(**key_args)
return self.set_by_key(_value, key_args)

def set_by_key(self, value, key_args):
built_key = self.key.build(key_args)
return self.storage.set(built_key, value)

def get_or_set(self, _value, *args, **kwargs):
key_args = self._key_args(args, kwargs)
value = self.get_by_key(key_args)
if value is None:
value = _value(**key_args)
self.set_by_key(value, key_args)
return value
22 changes: 22 additions & 0 deletions cachain/storage.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@


class Storage(object):

def get(self, key):
raise NotImplementedError

def set(self, key, value, expire=None):
raise NotImplementedError


class DictStorage(Storage):

def __init__(self, storage):
self.storage = storage

def get(self, key):
return self.storage.get(key)

def set(self, key, value, expire=None):
assert expire is None, 'expire is not supported'
return self.storage.update({key: value})
Empty file added tests/__init__.py
Empty file.
26 changes: 26 additions & 0 deletions tests/test_cachain.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@

from cachain.storage import DictStorage
from cachain.ingredient import Ring


import pytest


@pytest.fixture
def fx_ring():
storage = DictStorage({})
ring = Ring(storage, 'user_id:{user_id}')
return ring


def test_ring_get_set(fx_ring):
assert fx_ring.get({'user_id': 1}) is None
fx_ring.set(lambda user_id: 100, {'user_id': 1})


def test_ring_get_or_set(fx_ring):
assert fx_ring.get({'user_id': 1}) is None
assert fx_ring.get_or_set(lambda user_id: 100, {'user_id': 1}) == 100
assert fx_ring.get({'user_id': 1}) == 100


0 comments on commit 2026320

Please sign in to comment.