Skip to content

Commit ea804fb

Browse files
committed
Simplify API into builtins
1 parent 3e5eb6a commit ea804fb

11 files changed

+58
-126
lines changed

.pre-commit-config.yaml

+3-3
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
files: ^python/.*|^tests/.*|^src/.*
22
repos:
33
- repo: https://github.com/ambv/black
4-
rev: 21.11b1
4+
rev: 22.3.0
55
hooks:
66
- id: black
77
- repo: local
@@ -24,11 +24,11 @@ repos:
2424
- id: flake8
2525
args: ["--max-line-length=88"]
2626
- repo: https://github.com/pre-commit/mirrors-mypy
27-
rev: v0.910-1
27+
rev: v0.961
2828
hooks:
2929
- id: mypy
3030
- repo: https://github.com/pre-commit/pre-commit-hooks
31-
rev: v4.0.1
31+
rev: v4.3.0
3232
hooks:
3333
- id: end-of-file-fixer
3434
- id: trailing-whitespace

Cargo.lock

+1-1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "routrie"
3-
version = "0.2.0"
3+
version = "0.3.0"
44
edition = "2021"
55
description = "Rust port of the Python stdlib routrie modules"
66
readme = "README.md"

README.md

+14-10
Original file line numberDiff line numberDiff line change
@@ -24,25 +24,29 @@ assert matched is None
2424

2525
matched = router.find("/users/routrie")
2626
assert matched is not None
27-
assert matched.value == 2
28-
assert matched.params[0].name == "id"
29-
assert matched.params[0].value == "routrie"
27+
value, params = matched
28+
assert value == 2
29+
assert params[0].name == "id"
30+
assert params[0].value == "routrie"
3031

3132
matched = router.find("/users")
3233
assert matched is not None
33-
assert matched.value == 1
34-
assert matched.params == []
34+
value, params = matched
35+
assert value == 1
36+
assert params == []
3537

3638
matched = router.find("/users/repos/)
3739
assert matched is not None
38-
assert matched.value == 3
39-
assert matched.params == []
40+
value, params = matched
41+
assert value == 3
42+
assert params == []
4043

4144
matched = router.find("/users/repos/something)
4245
assert matched is not None
43-
assert matched.value == 3
44-
assert matched.params[0].name = "any"
45-
assert matched.params[0].value = "something"
46+
value, params = matched
47+
assert value == 3
48+
assert params[0].name = "any"
49+
assert params[0].value = "something"
4650
```
4751

4852
## Contributing

python/routrie/__init__.py

+5-7
Original file line numberDiff line numberDiff line change
@@ -2,25 +2,23 @@
22

33
import typing
44

5-
from routrie.routrie import Match, Param
6-
from routrie.routrie import Router as _Router
7-
8-
__all__ = ("Router", "Match", "Param")
9-
5+
from routrie._routrie import Router as _Router
106

117
T = typing.TypeVar("T")
128

9+
Params = typing.List[typing.Tuple[str, str]]
10+
1311

1412
class Router(typing.Generic[T]):
1513
__slots__ = ("_router",)
1614

17-
_router: _Router[T]
15+
_router: "_Router[T]"
1816

1917
def __init__(self) -> None:
2018
self._router = _Router()
2119

2220
def insert(self, path: str, value: T) -> None:
2321
self._router.insert(path, value)
2422

25-
def find(self, path: str) -> typing.Optional[Match[T]]:
23+
def find(self, path: str) -> typing.Tuple[T, Params]:
2624
return self._router.find(path)

python/routrie/_routrie.pyi

+9
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
from typing import Generic, List, Tuple, TypeVar
2+
3+
T = TypeVar("T")
4+
5+
Params = List[Tuple[str, str]]
6+
7+
class Router(Generic[T]):
8+
def insert(self, path: str, value: T, /) -> None: ...
9+
def find(self, path: str, /) -> Tuple[T, Params]: ...

python/routrie/routrie.pyi

-15
This file was deleted.

requirements-bench.txt

-3
This file was deleted.

requirements-dev.txt

+3-3
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
1-
pytest==6.2.5
2-
maturin==0.12.3
3-
pre-commit==2.16.0
1+
pytest==7.1.2
2+
maturin==0.13.0b6
3+
pre-commit==2.19.0

src/lib.rs

+2-69
Original file line numberDiff line numberDiff line change
@@ -1,58 +1,6 @@
11
use path_tree::PathTree;
22
use pyo3::prelude::*;
33

4-
#[pyclass(module = "routrie")]
5-
#[derive(Clone)]
6-
struct Param {
7-
#[pyo3(get)]
8-
name: String,
9-
#[pyo3(get)]
10-
value: String,
11-
}
12-
13-
impl Param {
14-
fn to_string(&self) -> String {
15-
format!("Param({}, {})", self.name, self.value)
16-
}
17-
}
18-
19-
#[pymethods]
20-
impl Param {
21-
fn __str__(&self) -> String {
22-
self.to_string()
23-
}
24-
fn __repr__(&self) -> String {
25-
self.to_string()
26-
}
27-
}
28-
29-
#[pyclass(module = "routrie")]
30-
#[derive(Clone)]
31-
struct Match {
32-
#[pyo3(get)]
33-
value: Py<PyAny>,
34-
#[pyo3(get)]
35-
params: Vec<Param>,
36-
}
37-
38-
#[pymethods]
39-
impl Match {
40-
fn __str__(&self) -> String {
41-
let params = format!(
42-
"[{}]",
43-
self.params
44-
.iter()
45-
.map(|param| format!("{}, ", param.to_string()))
46-
.collect::<Vec<String>>()
47-
.join(", ")
48-
);
49-
format!("Match({}, {})", self.value, params)
50-
}
51-
fn __repr__(&self) -> String {
52-
self.__str__()
53-
}
54-
}
55-
564
#[pyclass(module = "routrie._routrie")]
575
struct Router {
586
router: PathTree<Py<PyAny>>,
@@ -69,28 +17,13 @@ impl Router {
6917
fn insert(&mut self, path: &str, data: &PyAny, py: Python) -> () {
7018
self.router.insert(path, data.into_py(py));
7119
}
72-
fn find(&self, path: &str) -> Option<Match> {
73-
match self.router.find(path) {
74-
None => None,
75-
Some(found) => Some(Match {
76-
value: found.0.clone(),
77-
params: found
78-
.1
79-
.into_iter()
80-
.map(|(name, value)| Param {
81-
name: name.to_string(),
82-
value: value.to_string(),
83-
})
84-
.collect(),
85-
}),
86-
}
20+
fn find<'m>(&'m self, path: &'m str) -> Option<(&'m Py<PyAny>, Vec<(&'m str, &'m str)>)> {
21+
self.router.find(path)
8722
}
8823
}
8924

9025
#[pymodule]
9126
fn _routrie(_py: Python, m: &PyModule) -> PyResult<()> {
92-
m.add_class::<Param>()?;
93-
m.add_class::<Match>()?;
9427
m.add_class::<Router>()?;
9528
Ok(())
9629
}

test_routrie.py

+20-14
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,9 @@
1-
from typing import Iterable, List, Tuple
2-
31
import pytest
42

5-
from routrie import Router, Param
6-
3+
from routrie import Router
74

8-
def params_to_tuple(params: Iterable[Param]) -> List[Tuple[str, str]]:
9-
return [(p.name, p.value) for p in params]
105

11-
12-
def test_routing():
6+
def test_routing() -> None:
137
router: Router[int] = Router()
148
router.insert("/", 0)
159
router.insert("/users", 1)
@@ -28,20 +22,32 @@ def test_routing():
2822
# Matched "/"
2923
node = router.find("/")
3024
assert node is not None
31-
assert node.value == 0
32-
assert params_to_tuple(node.params) == []
25+
match, params = node
26+
assert match == 0
27+
assert params == []
3328

3429
# Matched "/:username"
3530
node = router.find("/username")
3631
assert node is not None
37-
assert node.value == 7
38-
assert params_to_tuple(node.params) == [("username", "username")]
32+
match, params = node
33+
assert match == 7
34+
assert params == [("username", "username")]
3935

4036
# Matched "/*any"
4137
node = router.find("/user/s")
4238
assert node is not None
43-
assert node.value == 8
44-
assert params_to_tuple(node.params) == [("any", "user/s")]
39+
match, params = node
40+
assert match == 8
41+
assert params == [("any", "user/s")]
42+
43+
44+
def test_no_match() -> None:
45+
router: Router[int] = Router()
46+
router.insert("/", 0)
47+
48+
# No match
49+
node = router.find("/noway-jose")
50+
assert node is None
4551

4652

4753
if __name__ == "__main__":

0 commit comments

Comments
 (0)