Skip to content

Commit

Permalink
Add type hints
Browse files Browse the repository at this point in the history
  • Loading branch information
diogok committed Jan 11, 2020
1 parent 3ccda04 commit df1bebc
Show file tree
Hide file tree
Showing 4 changed files with 47 additions and 30 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,4 @@ dist
build
*.egg-info
__pycache__
.mypy_cache/
5 changes: 4 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,10 @@ publish:
clean:
rm -Rf build dist *.egg-info

test:
test-type:
python3 -m mypy --strict py_matching_pattern

test: test-type
python3 -m unittest --failfast tests/test_core.py

test-single:
Expand Down
49 changes: 31 additions & 18 deletions py_matching_pattern/__init__.py
Original file line number Diff line number Diff line change
@@ -1,35 +1,47 @@

from threading import Lock
from copy import deepcopy
from uuid import uuid4
from uuid import uuid4,UUID
from typing import Sequence, TypeVar, Generic, Any, Dict, Mapping, Union, List

class InvalidKeySize(Exception):
pass

class InvalidKeyCount(Exception):
pass

class InvalidNodeInternalException(Exception):
pass

class KeyNotFound(Exception):
pass

class PatternMatchStore:
K = TypeVar('K')
V = TypeVar('V')

class PatternMatchStore(Generic[K,V]):

__default: UUID

default =None
__db: Mapping[Any,Any]
__lock: Lock
__stage: Dict[Any,Any]
__keysize: int
__raise_notfound: bool

def __init__(self,keysize=1,raise_notfound=False):
def __init__(self,keysize: int=1,raise_notfound: bool=False) -> None:
if keysize < 1:
raise InvalidKeySize

self.__db = {}
self.__lock = Lock()
self.__stage = {}
self.__keysize=keysize
self.__lock = Lock()

self.raise_notfound = raise_notfound
self.__raise_notfound = raise_notfound

self.default=uuid4()

def put(self,keys=[],value=None):
def put(self,keys: Sequence[K], value: V) -> None:
if(len(keys)<self.__keysize):
raise InvalidKeyCount

Expand All @@ -43,31 +55,31 @@ def put(self,keys=[],value=None):
node[key]={}
node=node[key]

def clean(self):
def clean(self) -> None:
self.__stage={}

def commit(self):
def commit(self) -> None:
dbcopy=deepcopy(self.__stage)
self.__lock.acquire(blocking=True,timeout=-1)
self.__db=dbcopy
self.__lock.release()

def get(self,keys=[]):
def get(self, keys: Sequence[K]) -> Union[V,None,Any]:
if(len(keys)<self.__keysize):
raise InvalidKeyCount

self.__lock.acquire(blocking=True,timeout=-1)
value = self.__get(keys=keys)
self.__lock.release()

if value is None and self.raise_notfound:
if value is None and self.__raise_notfound:
raise KeyNotFound

return value

def __default_filled(self,keys,key_mask):
def __default_filled(self,keys: Sequence[K], key_mask: str) -> Sequence[Union[K,UUID]]:
# TODO: there is a better solution
new_keys=[]
new_keys: List[Union[K,UUID]] =[]
for n in range(self.__keysize):
mask = key_mask[n]
if mask == "1":
Expand All @@ -77,13 +89,13 @@ def __default_filled(self,keys,key_mask):

return new_keys

def __get(self,keys=[]):
def __get(self,keys: Sequence[K]) -> Union[V,None,Any]:
int_limit = pow(2,self.__keysize)
current=1

while current <= int_limit:
key_mask = format(int_limit - current,f"0{self.__keysize}b") # eg 010101
current_keys = self.__default_filled(keys=keys,key_mask=key_mask) # zeros are default
key_mask: str = format(int_limit - current,f"0{self.__keysize}b") # eg 010101
current_keys: Sequence[Union[K,UUID]] = self.__default_filled(keys=keys,key_mask=key_mask) # zeros are default

node=self.__db

Expand All @@ -92,7 +104,8 @@ def __get(self,keys=[]):

if key in node:
if n+1 == self.__keysize:
return node[key]
v= node[key]
return v
node=node[key]
continue
else:
Expand Down
22 changes: 11 additions & 11 deletions tests/test_core.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import unittest
import py_matching_pattern as core
from py_matching_pattern import PatternMatchStore, KeyNotFound

class CoreTest(unittest.TestCase):

def test_basic(self):
mm = core.PatternMatchStore(keysize=3)
mm = PatternMatchStore(keysize=3)
_=mm.default

mm.put(keys=["a","b","c"],value=1)
Expand All @@ -22,7 +22,7 @@ def test_basic(self):
self.assertEqual(5,mm.get(keys=["a",None,"c"]))

def test_break_out_of_loop(self):
mm = core.PatternMatchStore(keysize=3)
mm = PatternMatchStore(keysize=3)
_=mm.default

mm.put(keys=["a","b","c"],value=1)
Expand All @@ -35,7 +35,7 @@ def test_break_out_of_loop(self):
self.assertEqual(None,mm.get(keys=["a","c","d"]))

def test_back_and_forth(self):
mm = core.PatternMatchStore(keysize=3)
mm = PatternMatchStore(keysize=3)
_=mm.default

mm.put(keys=["a","b","c"],value=1)
Expand All @@ -58,7 +58,7 @@ def test_back_and_forth(self):
self.assertEqual(None,mm.get(keys=["d","d","e"]))

def test_basic_unordered(self):
mm = core.PatternMatchStore(keysize=3)
mm = PatternMatchStore(keysize=3)
d=mm.default

mm.put(keys=["a","b",d],value=3)
Expand All @@ -74,26 +74,26 @@ def test_basic_unordered(self):
self.assertEqual(4,mm.get(keys=["a","c","d"]))

def test_basic_clean(self):
mm = core.PatternMatchStore(keysize=3,raise_notfound=True)
mm = PatternMatchStore(keysize=3,raise_notfound=True)

mm.put(keys=["a","b","c"],value=1)
mm.commit()
self.assertEqual(1,mm.get(keys=["a","b","c"]))

mm.clean()
mm.commit()
with self.assertRaises(core.KeyNotFound):
with self.assertRaises(KeyNotFound):
mm.get(keys=["a","b","c"])

def test_uncommited(self):
mm = core.PatternMatchStore(keysize=3,raise_notfound=True)
mm = PatternMatchStore(keysize=3,raise_notfound=True)

mm.put(keys=["a","b","c"],value=1)
with self.assertRaises(core.KeyNotFound):
with self.assertRaises(KeyNotFound):
mm.get(keys=["a","b","c"])

def test_uncommited_clean(self):
mm = core.PatternMatchStore(keysize=3)
mm = PatternMatchStore(keysize=3)

mm.put(keys=["a","b","c"],value=1)
mm.commit()
Expand All @@ -115,4 +115,4 @@ def test_invalid_keysize(self):
pass

def test_value_not_found(self):
pass
pass

0 comments on commit df1bebc

Please sign in to comment.