fresco 3.6.0__py3-none-any.whl → 3.7.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
fresco/__init__.py CHANGED
@@ -68,7 +68,7 @@ from fresco.subrequests import subrequest_raw
68
68
  from fresco.util.common import object_or_404
69
69
 
70
70
 
71
- __version__ = "3.6.0"
71
+ __version__ = "3.7.0"
72
72
  __all__ = [
73
73
  "Request",
74
74
  "currentrequest",
@@ -15,6 +15,7 @@
15
15
  from fresco.core import FrescoApp
16
16
  from fresco.util.urls import normpath, make_query
17
17
  from fresco.util.urls import is_safe_url
18
+ from fresco.util.urls import add_query
18
19
 
19
20
  # Greek letters as unicode strings (require multi-byte representation in UTF-8)
20
21
  alpha = b"\xce\xb1".decode("utf8")
@@ -174,3 +175,22 @@ class TestSafeURL(object):
174
175
  ]
175
176
  for u in unsafe:
176
177
  assert is_safe_url(u, allowed_hosts={"good.example.org"}) is False
178
+
179
+
180
+ class TestAddQuery:
181
+
182
+ def test_it_adds_query(self):
183
+ url = add_query("http://localhost", {"foo": "bar"})
184
+ assert url == "http://localhost?foo=bar"
185
+
186
+ def test_it_adds_query_from_list(self):
187
+ url = add_query("http://localhost", [("foo", "bar")])
188
+ assert url == "http://localhost?foo=bar"
189
+
190
+ def test_it_adds_query_from_keywords(self):
191
+ url = add_query("http://localhost", foo="bar")
192
+ assert url == "http://localhost?foo=bar"
193
+
194
+ def test_it_appends_query(self):
195
+ url = add_query("http://localhost?foo=bar", {"foo": "baz"})
196
+ assert url == "http://localhost?foo=bar&foo=baz"
fresco/util/urls.py CHANGED
@@ -23,6 +23,8 @@ from typing import List
23
23
  from urllib.parse import quote_plus
24
24
  from urllib.parse import urlparse
25
25
  from urllib.parse import urlunparse
26
+ from urllib.parse import urlencode
27
+ from urllib.parse import parse_qsl
26
28
  import posixpath
27
29
  import re
28
30
  import typing as t
@@ -31,7 +33,7 @@ from fresco.defaults import DEFAULT_CHARSET
31
33
  from fresco.multidict import MultiDict
32
34
  from fresco.types import QuerySpec
33
35
 
34
- __all__ = "join_path", "url_join", "strip_trailing_slashes", "normpath"
36
+ __all__ = "join_path", "url_join", "strip_trailing_slashes", "normpath", "add_query"
35
37
 
36
38
 
37
39
  def join_path(a, b):
@@ -329,3 +331,31 @@ def is_safe_url(
329
331
  or (scheme == "" and netloc == "")
330
332
  or (scheme == "" and netloc in allowed_hosts)
331
333
  )
334
+
335
+
336
+ def add_query(
337
+ url: str,
338
+ data: t.Union[t.Sequence[tuple[str, t.Any]], t.Mapping[str, t.Any]] = [],
339
+ **kwargs: t.Any,
340
+ ) -> str:
341
+ """
342
+ Return the given URL with the given query data appended
343
+
344
+ :param url:
345
+ The base URL
346
+ :param data:
347
+ Optional data items, supplied either as a mapping or list of (key,
348
+ value) tuples
349
+ :param kwargs:
350
+ Query data supplied as keyword arguments
351
+ """
352
+ parsed = urlparse(url)
353
+ return urlunparse(
354
+ parsed._replace(
355
+ query=urlencode(
356
+ parse_qsl(parsed.query)
357
+ + list(dict(data).items())
358
+ + list(kwargs.items())
359
+ )
360
+ )
361
+ )
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: fresco
3
- Version: 3.6.0
3
+ Version: 3.7.0
4
4
  Summary: A Web/WSGI micro-framework
5
5
  Author-email: Oliver Cope <oliver@redgecko.org>
6
6
  License: Apache
@@ -1,4 +1,4 @@
1
- fresco/__init__.py,sha256=02YPwizUXGa9L8OrpfoX9edVv6ISiCdIOyqR0LvYYWA,3537
1
+ fresco/__init__.py,sha256=Jo5gW2Xce2hmtXhfaXXJR4aBW1KFYb0Murx2JfIo_E8,3537
2
2
  fresco/cookie.py,sha256=Qnx8yOjU4LUJ1fqi7YvqbhAA01rCsclJGl_fxI68slw,7055
3
3
  fresco/core.py,sha256=bqGDgm4OH46j6HqnC5nJyn9n1dQw-I1ntUY8dIpeO_M,26988
4
4
  fresco/decorators.py,sha256=JL4MlsJz4RWRAuOCCB3fx3rtd-E1CvwO2MD7bf94yHM,3324
@@ -37,7 +37,7 @@ fresco/tests/util/form_data.py,sha256=TalOuv4BGM3JNrf14tE47o9wAwZ7jA1CvRDnGJFifn
37
37
  fresco/tests/util/test_common.py,sha256=NvKX8KIAUki7b2kDLILWqARbOQmR3XyInLlbcwFEhiU,1117
38
38
  fresco/tests/util/test_http.py,sha256=mdHDc-4m9sMNkEgHToIsgFuSSXQzNUcYSehPehYvJYo,10748
39
39
  fresco/tests/util/test_security.py,sha256=MtpDDKyDhAeRT766Lt3peOv4Jj55TM1lvJk1_5TKaes,1492
40
- fresco/tests/util/test_urls.py,sha256=xKiE6oq0bB-9u8kNYlMQmeCwuAKr1KLQovB-i24wKVQ,7643
40
+ fresco/tests/util/test_urls.py,sha256=U12T9MlP7zCpf-ufoyaZI5nAswi0xCSBOxHjHB2K_0I,8320
41
41
  fresco/tests/util/test_wsgi.py,sha256=VsHUCo8yck_40nsYm-H-M0R8QYEE8JcboeGPbcrzsO0,3038
42
42
  fresco/util/__init__.py,sha256=mJkaZzvYgBnxsBAGv8y_P1yzonHqWgw6VF2Zs4rmJEA,7
43
43
  fresco/util/cache.py,sha256=0xINmBecCYo3h5-zU_yRyJeWmROygE3pO9w9Y3ZONcs,1661
@@ -49,10 +49,10 @@ fresco/util/io.py,sha256=xxwDNJOcewY8lAR4Ce3cmB_zlrys8JGsESgwGWE198Y,1289
49
49
  fresco/util/object.py,sha256=FjYNfPHzvBqq1rn0Y6As-2AVZ_SZOjH-lrSy4EbYmHY,370
50
50
  fresco/util/security.py,sha256=nXEdoCak_2c4OA1L1wGwhZygS22s2fzwR0Kp-DdwKZg,1058
51
51
  fresco/util/textproc.py,sha256=e5jLTofKCqdm6_Fy8XOyR43AJr5APtL59Kd8cNA9PrQ,2309
52
- fresco/util/urls.py,sha256=2vDbfmjBLtUVpZ0ZhoNWkzn2WVZxcZZQeBZjtcUDp3w,9276
52
+ fresco/util/urls.py,sha256=V6-s2WgeARkEcuzpwqtiM8ebOXe5-mNUKOJ8N9LNBHA,10051
53
53
  fresco/util/wsgi.py,sha256=RYw4KeOUjzzPOL_HhEtgLyCngofjMdAT8BTLOSKU6KA,13021
54
- fresco-3.6.0.dist-info/licenses/LICENSE.txt,sha256=z8d0m5b2O9McPEK1xHG_dWgUBT6EfBDz6wA0F7xSPTA,11358
55
- fresco-3.6.0.dist-info/METADATA,sha256=zfjV8OUXV-2-dRpwNilk8cgduTx8ZUq8dw_IcClwnuQ,1571
56
- fresco-3.6.0.dist-info/WHEEL,sha256=GHB6lJx2juba1wDgXDNlMTyM13ckjBMKf-OnwgKOCtA,91
57
- fresco-3.6.0.dist-info/top_level.txt,sha256=p_1aMce5Shjq9fIfdbB-aN8wCDhjF_iYnn98bUebbII,7
58
- fresco-3.6.0.dist-info/RECORD,,
54
+ fresco-3.7.0.dist-info/licenses/LICENSE.txt,sha256=z8d0m5b2O9McPEK1xHG_dWgUBT6EfBDz6wA0F7xSPTA,11358
55
+ fresco-3.7.0.dist-info/METADATA,sha256=bqLRh85Q1K4S3Orlpyl-1vUXemvnWGrx1Y-qKtymOI0,1571
56
+ fresco-3.7.0.dist-info/WHEEL,sha256=0CuiUZ_p9E4cD6NyLD6UG80LBXYyiSYZOKDm5lp32xk,91
57
+ fresco-3.7.0.dist-info/top_level.txt,sha256=p_1aMce5Shjq9fIfdbB-aN8wCDhjF_iYnn98bUebbII,7
58
+ fresco-3.7.0.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: setuptools (80.3.0)
2
+ Generator: setuptools (80.3.1)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5