Implemented modular code structure
Refactored repository into kaya-core and kaya-rsgi packages
This commit is contained in:
@@ -0,0 +1,103 @@
|
||||
from typing import Sequence, Tuple, Optional, List
|
||||
|
||||
from kaya.core import Tree, PathHandler, HttpContext, HttpMethod, PathIterator
|
||||
from pwo import Maybe
|
||||
import unittest
|
||||
|
||||
|
||||
class PathIteratorTest(unittest.TestCase):
|
||||
cases: Tuple[Tuple[str, Tuple[str, ...]], ...] = (
|
||||
('/', tuple()),
|
||||
('root/foo', ('root', 'foo')),
|
||||
('/root', ('root',)),
|
||||
('/root', ('root',)),
|
||||
('/root/', ('root',)),
|
||||
('/root/bar/', ('root', 'bar')),
|
||||
)
|
||||
|
||||
def test_path_iterator(self):
|
||||
for (case, expected) in self.cases:
|
||||
with self.subTest(case) as _:
|
||||
components = tuple((c for c in PathIterator(case)))
|
||||
self.assertEqual(expected, components)
|
||||
|
||||
|
||||
class TreeTest(unittest.TestCase):
|
||||
tree: Tree
|
||||
handlers: List[PathHandler]
|
||||
|
||||
def setUp(self):
|
||||
self.tree = Tree()
|
||||
|
||||
class TestHandler(PathHandler):
|
||||
|
||||
def handle_request(self, ctx: HttpContext):
|
||||
pass
|
||||
|
||||
@property
|
||||
def recursive(self) -> bool:
|
||||
return True
|
||||
|
||||
self.handlers = [TestHandler() for _ in range(20)]
|
||||
|
||||
routes: Tuple[Tuple[Tuple[str, ...], Optional[HttpMethod], PathHandler], ...] = (
|
||||
(('home', 'something'), HttpMethod.GET, self.handlers[0]),
|
||||
(('home', 'something_else'), HttpMethod.GET, self.handlers[1]),
|
||||
(('home', 'something_else'), HttpMethod.POST, self.handlers[2]),
|
||||
(('home', 'something', 'object'), HttpMethod.GET, self.handlers[3]),
|
||||
(('home', 'something_else', 'foo'), HttpMethod.GET, self.handlers[4]),
|
||||
(('home',), HttpMethod.GET, self.handlers[5]),
|
||||
(('home',), HttpMethod.POST, self.handlers[6]),
|
||||
(('home',), None, self.handlers[7]),
|
||||
(('home', '*.md'), None, self.handlers[8]),
|
||||
(('home', 'something', '*', 'blah', '*.md'), None, self.handlers[9]),
|
||||
(('home', 'bar', '*'), None, self.handlers[10]),
|
||||
|
||||
)
|
||||
|
||||
for path, method, handler in routes:
|
||||
self.tree.add((p for p in path), method, handler)
|
||||
|
||||
def test_tree(self):
|
||||
|
||||
cases: Tuple[Tuple[str, HttpMethod, Optional[int]], ...] = (
|
||||
('http://localhost:127.0.0.1:5432/home/something', HttpMethod.GET, 0),
|
||||
('http://localhost:127.0.0.1:5432/home/something_else', HttpMethod.GET, 1),
|
||||
('http://localhost:127.0.0.1:5432/home/something_else', HttpMethod.POST, 2),
|
||||
('http://localhost:127.0.0.1:5432/home/something/object', HttpMethod.GET, 3),
|
||||
('http://localhost:127.0.0.1:5432/home/something_else/foo', HttpMethod.GET, 4),
|
||||
('http://localhost:127.0.0.1:5432/', HttpMethod.GET, None),
|
||||
('http://localhost:127.0.0.1:5432/home', HttpMethod.GET, 5),
|
||||
('http://localhost:127.0.0.1:5432/home', HttpMethod.POST, 6),
|
||||
('http://localhost:127.0.0.1:5432/home', HttpMethod.PUT, 7),
|
||||
('http://localhost:127.0.0.1:5432/home/README.md', HttpMethod.GET, 8),
|
||||
('http://localhost:127.0.0.1:5432/home/something/ciao/blah/README.md', HttpMethod.GET, 9),
|
||||
('http://localhost:127.0.0.1:5432/home/bar/ciao/blah/README.md', HttpMethod.GET, 10),
|
||||
)
|
||||
for url, method, handler_num in cases:
|
||||
with self.subTest(f"{str(method)} {url}"):
|
||||
res = self.tree.get_handler(url, method)
|
||||
self.assertIs(Maybe.of(handler_num).map(self.handlers.__getitem__).or_none(),
|
||||
Maybe.of_nullable(res).map(lambda it: it[0]).or_none())
|
||||
|
||||
def test_two_method_agnostic_matchers_raise(self):
|
||||
tree = Tree()
|
||||
tree.add((p for p in ('foo', '*')), None, self.handlers[0])
|
||||
with self.assertRaises(ValueError):
|
||||
tree.add((p for p in ('foo', '*')), None, self.handlers[1])
|
||||
|
||||
def test_two_overlapping_method_specific_matchers_raise(self):
|
||||
tree = Tree()
|
||||
tree.add((p for p in ('foo', '${id:int}')), HttpMethod.PUT, self.handlers[0])
|
||||
with self.assertRaises(ValueError):
|
||||
tree.add((p for p in ('foo', '${name:str}')), HttpMethod.PUT, self.handlers[1])
|
||||
|
||||
def test_disjoint_method_specific_matchers_allowed(self):
|
||||
tree = Tree()
|
||||
tree.add((p for p in ('foo', '*')), HttpMethod.PUT, self.handlers[0])
|
||||
tree.add((p for p in ('foo', '*')), HttpMethod.GET, self.handlers[1])
|
||||
put_handler = Maybe.of_nullable(tree.get_handler('/foo/bar', HttpMethod.PUT)).map(lambda it: it[0]).or_none()
|
||||
get_handler = Maybe.of_nullable(tree.get_handler('/foo/bar', HttpMethod.GET)).map(lambda it: it[0]).or_none()
|
||||
self.assertIs(self.handlers[0], put_handler)
|
||||
self.assertIs(self.handlers[1], get_handler)
|
||||
|
||||
Reference in New Issue
Block a user