Skip to content

Commit ff62516

Browse files
committed
shortener WIP
1 parent 3139c8f commit ff62516

File tree

2 files changed

+52
-20
lines changed

2 files changed

+52
-20
lines changed

links/shortener.py

Lines changed: 26 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,16 @@
1+
"""
2+
URL shortener for .htaccess redirects
3+
4+
Procedure:
5+
6+
0. create empty dicts named targets and redirects
7+
1. given a target_url, find it in targets;
8+
1.1. if found, use the short_url stored there
9+
1.2. if not, generate new short_url and store it in targets and redirects
10+
11+
"""
12+
13+
114
from collections.abc import Iterable, Iterator
215

316

@@ -14,21 +27,23 @@ def parse_htaccess(text: str) -> Iterator[tuple[str, str]]:
1427

1528

1629
def choose(a: str, b: str) -> str:
17-
def key(k):
30+
def key(k: str) -> tuple[int, bool, list[str]]:
1831
parts = k.split('-')
1932
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)
33+
parts = [(f'z{p:>08}' if p.isnumeric() else p) for p in parts]
34+
return len(k), '-' in k, parts
2235
return min(a, b, key=key)
2336

2437

2538
def load_redirects(pairs: Iterable[tuple[str, str]]) -> tuple[dict, dict]:
2639
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-
40+
targets = {}
41+
for short_url, url in pairs:
42+
url = redirects.setdefault(short_url, url)
43+
existing_short_url = targets.get(url)
44+
if existing_short_url is None:
45+
targets[url] = short_url
46+
else:
47+
targets[url] = choose(short_url, existing_short_url)
48+
49+
return redirects, targets

links/test_shortener.py

Lines changed: 26 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
from pytest import mark
22

3-
from shortener import parse_htaccess, choose
3+
from shortener import parse_htaccess, choose, load_redirects
44

55

66
HTACCESS_1 = """
@@ -13,14 +13,17 @@
1313
# duplicate targets
1414
RedirectTemp /1-20 https://www.fluentpython.com/
1515
RedirectTemp /ora https://www.oreilly.com/.../9781492056348/
16-
16+
RedirectTemp /2-10 http://example.com/
17+
RedirectTemp /10-2 http://example.com/
1718
"""
1819

1920
PARSED_HTACCESS_1 = [
2021
('book', 'https://www.oreilly.com/.../9781492056348/'),
2122
('home', 'https://www.fluentpython.com/'),
2223
('1-20', 'https://www.fluentpython.com/'),
2324
('ora', 'https://www.oreilly.com/.../9781492056348/'),
25+
('2-10', 'http://example.com/'),
26+
('10-2', 'http://example.com/'),
2427
]
2528

2629
def test_parse_htaccess():
@@ -40,10 +43,24 @@ def test_choose(a, b, expected):
4043
assert res == expected
4144

4245

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
46+
def test_load_redirects():
47+
expected = {
48+
'home': 'https://www.fluentpython.com/',
49+
'1-20': 'https://www.fluentpython.com/',
50+
'2-10': 'http://example.com/',
51+
'10-2': 'http://example.com/',
52+
'book': 'https://www.oreilly.com/.../9781492056348/',
53+
'ora': 'https://www.oreilly.com/.../9781492056348/',
54+
}
55+
redirects, _ = load_redirects(PARSED_HTACCESS_1)
56+
assert redirects == expected
57+
58+
59+
def test_load_redirect_targets():
60+
expected = {
61+
'https://www.fluentpython.com/' : 'home',
62+
'https://www.oreilly.com/.../9781492056348/' : 'ora',
63+
'http://example.com/' : '2-10',
64+
}
65+
_, targets = load_redirects(PARSED_HTACCESS_1)
66+
assert targets == expected

0 commit comments

Comments
 (0)