Eradicate the dedupe_qs filter

The new `extend_query` and `urlencode` filters are way cleaner ways
to achieve what we did with `dedupe_qs`.

Signed-off-by: Kevin Morris <kevr@0cost.org>
This commit is contained in:
Kevin Morris 2021-08-31 14:27:16 -07:00
parent c9374732c0
commit 210e459ba9
No known key found for this signature in database
GPG key ID: F7E46DED420788F3
5 changed files with 11 additions and 53 deletions

View file

@ -5,7 +5,6 @@ import typing
from datetime import datetime from datetime import datetime
from http import HTTPStatus from http import HTTPStatus
from urllib.parse import quote_plus
from fastapi import APIRouter, Form, HTTPException, Request from fastapi import APIRouter, Form, HTTPException, Request
from fastapi.responses import RedirectResponse, Response from fastapi.responses import RedirectResponse, Response
@ -106,12 +105,12 @@ async def trusted_user(request: Request,
context["current_by_next"] = "asc" if current_by == "desc" else "desc" context["current_by_next"] = "asc" if current_by == "desc" else "desc"
context["past_by_next"] = "asc" if past_by == "desc" else "desc" context["past_by_next"] = "asc" if past_by == "desc" else "desc"
context["q"] = '&'.join([ context["q"] = {
f"coff={current_off}", "coff": current_off,
f"cby={quote_plus(current_by)}", "cby": current_by,
f"poff={past_off}", "poff": past_off,
f"pby={quote_plus(past_by)}" "pby": past_by
]) }
return render_template(request, "tu/index.html", context) return render_template(request, "tu/index.html", context)

View file

@ -30,7 +30,6 @@ _env.filters["tn"] = l10n.tn
# Utility filters. # Utility filters.
_env.filters["dt"] = util.timestamp_to_datetime _env.filters["dt"] = util.timestamp_to_datetime
_env.filters["as_timezone"] = util.as_timezone _env.filters["as_timezone"] = util.as_timezone
_env.filters["dedupe_qs"] = util.dedupe_qs
_env.filters["extend_query"] = util.extend_query _env.filters["extend_query"] = util.extend_query
_env.filters["urlencode"] = util.to_qs _env.filters["urlencode"] = util.to_qs
_env.filters["quote_plus"] = quote_plus _env.filters["quote_plus"] = quote_plus

View file

@ -6,10 +6,9 @@ import re
import secrets import secrets
import string import string
from collections import OrderedDict
from datetime import datetime from datetime import datetime
from typing import Any, Dict from typing import Any, Dict
from urllib.parse import quote_plus, urlencode, urlparse from urllib.parse import urlencode, urlparse
from zoneinfo import ZoneInfo from zoneinfo import ZoneInfo
import fastapi import fastapi
@ -126,31 +125,8 @@ def as_timezone(dt: datetime, timezone: str):
return dt.astimezone(tz=ZoneInfo(timezone)) return dt.astimezone(tz=ZoneInfo(timezone))
def dedupe_qs(query_string: str, *additions):
""" Dedupe keys found in a query string by rewriting it without
duplicates found while iterating from the end to the beginning,
using an ordered memo to track keys found and persist locations.
That is, query string 'a=1&b=1&a=2' will be deduped and converted
to 'b=1&a=2'.
:param query_string: An HTTP URL query string.
:param *additions: Optional additional fields to add to the query string.
:return: Deduped query string, including *additions at the tail.
"""
for addition in list(additions):
query_string += f"&{addition}"
qs = OrderedDict()
for item in reversed(query_string.split('&')):
key, value = item.split('=')
if key not in qs:
qs[key] = value
return '&'.join([f"{k}={quote_plus(v)}" for k, v in reversed(qs.items())])
def extend_query(query: Dict[str, Any], *additions) -> Dict[str, Any]: def extend_query(query: Dict[str, Any], *additions) -> Dict[str, Any]:
""" Add additionally key value pairs to query. """ """ Add additional key value pairs to query. """
for k, v in list(additions): for k, v in list(additions):
query[k] = v query[k] = v
return query return query

View file

@ -24,7 +24,7 @@
<th> <th>
{% set off_qs = "%s=%d" | format(off_param, off) %} {% set off_qs = "%s=%d" | format(off_param, off) %}
{% set by_qs = "%s=%s" | format(by_param, by_next | quote_plus) %} {% set by_qs = "%s=%s" | format(by_param, by_next | quote_plus) %}
<a href="?{{ q | dedupe_qs(off_qs, by_qs) }}"> <a href="?{{ q | extend_query([off_param, off], [by_param, by_next]) | urlencode }}">
{{ "Start" | tr }} {{ "Start" | tr }}
</a> </a>
</th> </th>
@ -97,7 +97,7 @@
{% set off_qs = "%s=%d" | format(off_param, off - 10) %} {% set off_qs = "%s=%d" | format(off_param, off - 10) %}
{% set by_qs = "%s=%s" | format(by_param, by | quote_plus) %} {% set by_qs = "%s=%s" | format(by_param, by | quote_plus) %}
<a class="page" <a class="page"
href="?{{ q | dedupe_qs(off_qs, by_qs) }}"> href="?{{ q | extend_query([off_param, ([off - 10, 0] | max)], [by_param, by]) | urlencode }}">
Back Back
</a> </a>
{% endif %} {% endif %}
@ -106,7 +106,7 @@
{% set off_qs = "%s=%d" | format(off_param, off + 10) %} {% set off_qs = "%s=%d" | format(off_param, off + 10) %}
{% set by_qs = "%s=%s" | format(by_param, by | quote_plus) %} {% set by_qs = "%s=%s" | format(by_param, by | quote_plus) %}
<a class="page" <a class="page"
href="?{{ q | dedupe_qs(off_qs, by_qs) }}"> href="?{{ q | extend_query([off_param, off + pp], [by_param, by]) | urlencode }}">
Next Next
</a> </a>
{% endif %} {% endif %}

View file

@ -1,4 +1,3 @@
from collections import OrderedDict
from datetime import datetime from datetime import datetime
from zoneinfo import ZoneInfo from zoneinfo import ZoneInfo
@ -17,21 +16,6 @@ def test_as_timezone():
assert util.as_timezone(dt, "UTC") == dt.astimezone(tz=ZoneInfo("UTC")) assert util.as_timezone(dt, "UTC") == dt.astimezone(tz=ZoneInfo("UTC"))
def test_dedupe_qs():
items = OrderedDict()
items["key1"] = "test"
items["key2"] = "blah"
items["key3"] = 1
# Construct and test our query string.
query_string = '&'.join([f"{k}={v}" for k, v in items.items()])
assert query_string == "key1=test&key2=blah&key3=1"
# Add key1=changed and key2=changed to the query and dedupe it.
deduped = util.dedupe_qs(query_string, "key1=changed", "key3=changed")
assert deduped == "key2=blah&key1=changed&key3=changed"
def test_number_format(): def test_number_format():
assert util.number_format(0.222, 2) == "0.22" assert util.number_format(0.222, 2) == "0.22"
assert util.number_format(0.226, 2) == "0.23" assert util.number_format(0.226, 2) == "0.23"