Skip to content

Commit 3139c8f

Browse files
committed
shortener v2
1 parent 55abb0c commit 3139c8f

4 files changed

Lines changed: 89 additions & 2 deletions

File tree

links/shorten.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,8 +30,8 @@
3030
type TargetMap = dict[Url, ShortCode]
3131

3232
class ShortPair(NamedTuple):
33-
code = ShortCode
34-
url = Url
33+
code: ShortCode
34+
url: Url
3535

3636
def load_redirects() -> tuple[RedirMap, TargetMap]:
3737
redirects:RedirMap = {}

links/shortener.py

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
from collections.abc import Iterable, Iterator
2+
3+
4+
def parse_htaccess(text: str) -> Iterator[tuple[str, str]]:
5+
for line in text.splitlines():
6+
fields = line.split()
7+
if len(fields) < 3 or fields[0] != 'RedirectTemp':
8+
continue
9+
key = fields[1]
10+
assert key[0] == '/'
11+
key = key[1:]
12+
assert len(key) > 0
13+
yield (key, fields[2])
14+
15+
16+
def choose(a: str, b: str) -> str:
17+
def key(k):
18+
parts = k.split('-')
19+
if len(parts) > 1:
20+
parts = ['z' + p.rjust(8, '0') if p.isnumeric() else p for p in parts]
21+
return (len(k), '-' in k, parts)
22+
return min(a, b, key=key)
23+
24+
25+
def load_redirects(pairs: Iterable[tuple[str, str]]) -> tuple[dict, dict]:
26+
redirects = {}
27+
for key, url in pairs:
28+
existing_url = redirects.get(key)
29+
if existing_url:
30+
if len(existing_url) < len(url):
31+
continue
32+
elif len(existing_url) == len(url):
33+
url = choose(existing_url, url)
34+

links/test_shortener.py

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
from pytest import mark
2+
3+
from shortener import parse_htaccess, choose
4+
5+
6+
HTACCESS_1 = """
7+
ErrorDocument 404 /404.html
8+
9+
# main resources
10+
RedirectTemp /book https://www.oreilly.com/.../9781492056348/
11+
RedirectTemp /home https://www.fluentpython.com/ # extra content site
12+
13+
# duplicate targets
14+
RedirectTemp /1-20 https://www.fluentpython.com/
15+
RedirectTemp /ora https://www.oreilly.com/.../9781492056348/
16+
17+
"""
18+
19+
PARSED_HTACCESS_1 = [
20+
('book', 'https://www.oreilly.com/.../9781492056348/'),
21+
('home', 'https://www.fluentpython.com/'),
22+
('1-20', 'https://www.fluentpython.com/'),
23+
('ora', 'https://www.oreilly.com/.../9781492056348/'),
24+
]
25+
26+
def test_parse_htaccess():
27+
res = list(parse_htaccess(HTACCESS_1))
28+
assert res == PARSED_HTACCESS_1
29+
30+
@mark.parametrize('a,b,expected', [
31+
('a', 'b', 'a'),
32+
('b', 'a', 'a'),
33+
('aa', 'a', 'a'),
34+
('a-a', 'aaa', 'aaa'),
35+
('2-10', '10-2', '2-10'),
36+
('p-1', '1-1', 'p-1'),
37+
])
38+
def test_choose(a, b, expected):
39+
res = choose(a, b)
40+
assert res == expected
41+
42+
43+
# def test_load_redirects():
44+
# expected = {
45+
# 'home': 'https://www.fluentpython.com/',
46+
# 'ora': 'https://www.oreilly.com/.../9781492056348/'
47+
# }
48+
# redirects, _ = load_redirects(PARSED_HTACCESS_1)
49+
# assert redirects == expected

ruff.toml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
line-length = 100
2+
[format]
3+
# Use single quotes for strings, like Python's repr()
4+
quote-style = "single"

0 commit comments

Comments
 (0)