fresco 3.3.4__py3-none-any.whl → 3.9.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/util/http.py CHANGED
@@ -20,6 +20,8 @@ Utilities for working with data on the HTTP level
20
20
  from binascii import hexlify
21
21
  from collections import namedtuple
22
22
  from collections import deque
23
+ from collections.abc import Collection
24
+ from collections.abc import Mapping
23
25
  from email.header import Header
24
26
  from email.message import Message
25
27
  from email.parser import BytesFeedParser
@@ -43,6 +45,7 @@ from urllib.parse import unquote_plus
43
45
  from shutil import copyfileobj
44
46
 
45
47
  import fresco
48
+ from fresco.defaults import DEFAULT_CHARSET
46
49
  from fresco.exceptions import RequestParseError
47
50
  from fresco.util.io import io_iterator
48
51
  from fresco.util.io import ByteIterator
@@ -90,23 +93,23 @@ def get_content_type_info(
90
93
 
91
94
 
92
95
  class TooBig(RequestParseError):
93
- """\
96
+ """
94
97
  Request body is too big
95
98
  """
96
99
 
97
100
  def __init__(self, *args, **kwargs):
98
101
  super(TooBig, self).__init__(*args, **kwargs)
99
- self.response = fresco.response.Response.payload_too_large()
102
+ self.response = fresco.Response.payload_too_large()
100
103
 
101
104
 
102
105
  class MissingContentLength(RequestParseError):
103
- """\
106
+ """
104
107
  No ``Content-Length`` header given
105
108
  """
106
109
 
107
110
  def __init__(self, *args, **kwargs):
108
111
  super(MissingContentLength, self).__init__(*args, **kwargs)
109
- self.response = fresco.response.Response.length_required()
112
+ self.response = fresco.Response.length_required()
110
113
 
111
114
 
112
115
  def parse_parameters(s, preserve_backslashes=False) -> Dict[str, str]:
@@ -212,7 +215,7 @@ def parse_querystring(
212
215
 
213
216
  :param data: The query string to parse.
214
217
  :param charset: Character encoding used to decode values. If not specified,
215
- ``fresco.DEFAULT_CHARSET`` will be used.
218
+ ``fresco.defaults.DEFAULT_CHARSET`` will be used.
216
219
 
217
220
  :param keep_blank_values: if True, keys without associated values will be
218
221
  returned as empty strings. if False, no key,
@@ -223,7 +226,7 @@ def parse_querystring(
223
226
  """
224
227
 
225
228
  if charset is None:
226
- charset = fresco.DEFAULT_CHARSET
229
+ charset = DEFAULT_CHARSET
227
230
 
228
231
  result: List[Tuple[str, str]] = []
229
232
  append = result.append
@@ -275,7 +278,7 @@ def parse_post(
275
278
  ct, charset, ct_params = get_content_type_info(
276
279
  environ,
277
280
  "application/x-www-form-urlencoded",
278
- default_charset or fresco.DEFAULT_CHARSET,
281
+ default_charset or DEFAULT_CHARSET,
279
282
  )
280
283
 
281
284
  try:
@@ -454,14 +457,15 @@ def parse_multipart(
454
457
  f.close()
455
458
  raise
456
459
 
457
- close: Optional[Callable]
460
+ close: Optional[Callable] # type: ignore
458
461
  if open_files:
459
462
 
460
463
  def close():
461
464
  for f in open_files:
462
465
  f.close()
466
+
463
467
  else:
464
- close = None
468
+ close = None # type: ignore
465
469
 
466
470
  return fields, close
467
471
 
@@ -554,7 +558,6 @@ def read_until(
554
558
  return
555
559
 
556
560
  def remainder():
557
- nonlocal buf
558
561
  if buf:
559
562
  yield buf
560
563
  yield from stream
@@ -591,7 +594,21 @@ class FileUpload(object):
591
594
  copyfileobj(self.file, fileob)
592
595
 
593
596
 
594
- def encode_multipart(data=None, files=None, charset="UTF-8", **kwargs):
597
+ def encode_multipart(
598
+ data: Optional[
599
+ Union[
600
+ Mapping[str, str],
601
+ Collection[tuple[str, str]],
602
+ ]
603
+ ] = None,
604
+ files: Optional[
605
+ Collection[
606
+ tuple[str, str, str, Union[bytes, t.Iterable[bytes], t.BinaryIO]]
607
+ ]
608
+ ] = None,
609
+ charset="UTF-8",
610
+ **kwargs
611
+ ) -> tuple[bytes, dict[str, str]]:
595
612
  """
596
613
  Encode ``data`` using multipart/form-data encoding, returning a tuple
597
614
  of ``(<encoded data>, <environ items>)``.
@@ -602,7 +619,7 @@ def encode_multipart(data=None, files=None, charset="UTF-8", **kwargs):
602
619
  :param charset: Encoding used for any string values encountered in
603
620
  ``data``
604
621
 
605
- :param files: list of ``(name, filename, content_type, data)`` tuples.
622
+ :param files: collection of ``(name, filename, content_type, data)`` tuples.
606
623
  ``data`` may be either a byte string, iterator or
607
624
  file-like object.
608
625
 
@@ -614,45 +631,22 @@ def encode_multipart(data=None, files=None, charset="UTF-8", **kwargs):
614
631
  dict.
615
632
  """
616
633
 
617
- def header_block(name):
618
- return [("Content-Disposition", 'form-data; name="%s"' % (name,))]
619
-
620
- def file_header_block(name, filename, content_type):
621
- return [
622
- (
623
- "Content-Disposition",
624
- 'form-data; name="%s"; filename="%s"' % (name, filename),
625
- ),
626
- ("Content-Type", content_type),
627
- ]
628
-
629
- def write_payload(stream, data):
630
- "Write ``data`` to ``stream``, encoding as required"
631
- if hasattr(data, "read"):
632
- copyfileobj(data, stream)
633
- elif isinstance(data, bytes):
634
- stream.write(data)
635
- elif isinstance(data, str):
636
- stream.write(data.encode(charset))
637
- else:
638
- raise ValueError(data)
639
-
640
- if data is None:
641
- data = {}
642
-
643
634
  if files is None:
644
635
  files = []
645
636
 
646
- try:
647
- data = data.items()
648
- except AttributeError:
649
- pass
637
+ data_items: Iterable[tuple[str, str]]
638
+ if data is None:
639
+ data_items = []
640
+ elif isinstance(data, Mapping):
641
+ data_items = iter(data.items()) # type: ignore
642
+ else:
643
+ data_items = data
650
644
 
651
- data = chain(data, kwargs.items())
645
+ data_items = chain(data_items, kwargs.items())
652
646
 
653
647
  boundary = b"-------" + hexlify(os.urandom(16))
654
648
  alldata = chain(
655
- ((header_block(k), payload) for k, payload in data),
649
+ ((header_block(k), payload) for k, payload in data_items),
656
650
  ((file_header_block(k, fn, ct), payload) for k, fn, ct, payload in files),
657
651
  )
658
652
 
@@ -664,7 +658,7 @@ def encode_multipart(data=None, files=None, charset="UTF-8", **kwargs):
664
658
  for name, value in headers:
665
659
  post_data.write("{0}: {1}\r\n".format(name, value).encode("ascii"))
666
660
  post_data.write(CRLF)
667
- write_payload(post_data, payload)
661
+ write_payload(post_data, payload, charset)
668
662
  post_data.write(b"\r\n--" + boundary)
669
663
  post_data.write(b"--\r\n")
670
664
  length = post_data.tell()
@@ -676,4 +670,30 @@ def encode_multipart(data=None, files=None, charset="UTF-8", **kwargs):
676
670
  ),
677
671
  }
678
672
 
679
- return (post_data, wsgienv)
673
+ return (post_data.getvalue(), wsgienv)
674
+
675
+
676
+ def header_block(name):
677
+ return [("Content-Disposition", 'form-data; name="%s"' % (name,))]
678
+
679
+
680
+ def file_header_block(name, filename, content_type):
681
+ return [
682
+ (
683
+ "Content-Disposition",
684
+ 'form-data; name="%s"; filename="%s"' % (name, filename),
685
+ ),
686
+ ("Content-Type", content_type),
687
+ ]
688
+
689
+
690
+ def write_payload(stream, data, charset):
691
+ "Write ``data`` to ``stream``, encoding as required"
692
+ if hasattr(data, "read"):
693
+ copyfileobj(data, stream)
694
+ elif isinstance(data, bytes):
695
+ stream.write(data)
696
+ elif isinstance(data, str):
697
+ stream.write(data.encode(charset))
698
+ else:
699
+ raise ValueError(data)
fresco/util/urls.py CHANGED
@@ -23,15 +23,17 @@ 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
29
31
 
30
- import fresco
32
+ 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):
@@ -174,13 +176,13 @@ def make_query(
174
176
  data: QuerySpec = [],
175
177
  separator: str = "&",
176
178
  charset: t.Optional[str] = None,
177
- **kwargs,
179
+ **kwargs: t.Any,
178
180
  ) -> str:
179
181
  """
180
182
  Return a query string formed from the given dictionary data.
181
183
 
182
184
  If no encoding is given, unicode values are encoded using the character set
183
- specified by ``fresco.DEFAULT_CHARSET``.
185
+ specified by ``fresco.defaults.DEFAULT_CHARSET``.
184
186
 
185
187
  Basic usage::
186
188
 
@@ -210,46 +212,48 @@ def make_query(
210
212
  :param charset: encoding to be used for unicode values
211
213
  :rtype: str
212
214
  """
213
- items: t.Iterable[t.Tuple[str, t.Any]]
215
+ items: t.Iterable[tuple[str, t.Any]]
214
216
  if isinstance(data, MultiDict):
215
217
  items = data.allitems()
216
218
  elif isinstance(data, Mapping):
217
- items = data.items()
219
+ items = data.items() # type: ignore
218
220
  else:
219
221
  items = data
220
222
  if kwargs:
221
223
  items = chain(items, kwargs.items())
222
224
 
223
225
  if charset is None:
224
- charset = fresco.DEFAULT_CHARSET
226
+ charset = DEFAULT_CHARSET
225
227
 
226
- pairs: List[str] = []
228
+ pairs: list[str] = []
227
229
  append = pairs.append
228
230
  for k, v in items:
229
231
  if isinstance(v, (str, bytes)):
230
232
  append(f"{quote_plus(k, charset)}={quote_plus(v, charset)}")
233
+ elif v is None:
234
+ pass
231
235
  elif hasattr(v, "__iter__"):
232
236
  for v in v:
233
237
  append(f"{quote_plus(k, charset)}={quote_plus(str(v), charset)}")
234
- elif v is not None:
238
+ else:
235
239
  append(f"{quote_plus(k, charset)}={quote_plus(str(v), charset)}")
236
240
  return separator.join(pairs)
237
241
 
238
242
 
239
243
  def _qs_frag(key, value, charset=None):
240
- """\
244
+ """
241
245
  Return a fragment of a query string in the format 'key=value'::
242
246
 
243
247
  >>> _qs_frag('search-by', 'author, editor')
244
248
  'search-by=author%2C+editor'
245
249
 
246
250
  If no encoding is specified, unicode values are encoded using the character
247
- set specified by ``fresco.DEFAULT_CHARSET``.
251
+ set specified by ``fresco.defaults.DEFAULT_CHARSET``.
248
252
 
249
253
  :rtype: str
250
254
  """
251
255
  if charset is None:
252
- charset = fresco.DEFAULT_CHARSET
256
+ charset = DEFAULT_CHARSET
253
257
 
254
258
  key = str(key).encode(charset)
255
259
  value = str(value).encode(charset)
@@ -327,3 +331,31 @@ def is_safe_url(
327
331
  or (scheme == "" and netloc == "")
328
332
  or (scheme == "" and netloc in allowed_hosts)
329
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
+ )
fresco/util/wsgi.py CHANGED
@@ -22,15 +22,16 @@ from io import BytesIO
22
22
  from urllib.parse import unquote
23
23
  from urllib.parse import urlparse
24
24
  from typing import List
25
- from typing import Optional
26
- from typing import Tuple
25
+ import typing as t
27
26
  import sys
28
27
 
29
- from fresco.typing import ExcInfoTuple
30
- from fresco.typing import HeadersList
31
- from fresco.typing import WSGICallable
28
+ from fresco.types import WSGIApplication
29
+ from fresco.types import WriteCallable
30
+ from fresco.types import OptionalExcInfo
31
+ from fresco.types import HeaderList
32
32
 
33
33
  logger = logging.getLogger(__name__)
34
+ T = t.TypeVar("T")
34
35
 
35
36
 
36
37
  __all__ = [
@@ -102,7 +103,6 @@ REQUEST_HEADER_NAMES = {
102
103
  "dnt": "DNT",
103
104
  "x_forwarded_for": "X-Forwarded-For",
104
105
  "x_forwarded_host": "X-Forwarded-Host",
105
- "x_forwarded_host": "X-Forwarded-Host",
106
106
  "x_forwarded_proto": "X-Forwarded-Proto",
107
107
  "front_end_https": "Front-End-Https",
108
108
  "x_http_method_override": "X-Http-Method-Override",
@@ -245,8 +245,8 @@ class StartResponseWrapper(object):
245
245
  self.exc_info = None
246
246
 
247
247
 
248
- class ClosingIterator(object):
249
- """\
248
+ class ClosingIterator(t.Generic[T]):
249
+ """
250
250
  Wrap a WSGI iterator to allow additional close functions to be called on
251
251
  application exit.
252
252
 
@@ -275,7 +275,7 @@ class ClosingIterator(object):
275
275
 
276
276
  __slots__ = ("_iterable", "_next", "_close_funcs", "_closed")
277
277
 
278
- def __init__(self, iterable, *close_funcs):
278
+ def __init__(self, iterable: t.Iterable[T], *close_funcs: t.Callable[[], None]):
279
279
  """
280
280
  Initialize a ``ClosingIterator`` to wrap iterable ``iterable``, and
281
281
  call any functions listed in ``*close_funcs`` on the instance's
@@ -406,19 +406,20 @@ def make_environ(url="/", environ=None, wsgi_input=b"", **kwargs):
406
406
 
407
407
 
408
408
  def apply_request(
409
- request, wsgicallable: WSGICallable
410
- ) -> Tuple[str, HeadersList, Optional[ExcInfoTuple], List[bytes]]:
409
+ request, wsgicallable: WSGIApplication
410
+ ) -> tuple[str, HeaderList, OptionalExcInfo, list[bytes]]:
411
411
  """
412
412
  Execute ``wsgicallable`` with the given request, exhaust and close the
413
413
  content iterator and return the result.
414
414
  """
415
415
 
416
- _start_response_result: List[Tuple[str, HeadersList, Optional[ExcInfoTuple]]] = []
416
+ _start_response_result: list[tuple[str, HeaderList, OptionalExcInfo]] = []
417
417
 
418
418
  def start_response(
419
- status: str, headers: HeadersList, exc_info: Optional[ExcInfoTuple] = None
420
- ):
419
+ status: str, headers: HeaderList, exc_info: OptionalExcInfo = None
420
+ ) -> WriteCallable:
421
421
  _start_response_result.append((status, headers, exc_info))
422
+ return lambda s: None
422
423
 
423
424
  contentiter = wsgicallable(request.environ, start_response)
424
425
  assert len(_start_response_result) == 1
@@ -1,21 +1,21 @@
1
- Metadata-Version: 2.1
1
+ Metadata-Version: 2.4
2
2
  Name: fresco
3
- Version: 3.3.4
3
+ Version: 3.9.0
4
4
  Summary: A Web/WSGI micro-framework
5
5
  Author-email: Oliver Cope <oliver@redgecko.org>
6
- License: Apache
6
+ License-Expression: Apache-2.0
7
7
  Project-URL: Homepage, https://ollycope.com/software/fresco/latest/
8
8
  Keywords: wsgi,web,www,framework
9
9
  Classifier: Development Status :: 5 - Production/Stable
10
10
  Classifier: Environment :: Web Environment
11
11
  Classifier: Intended Audience :: Developers
12
- Classifier: License :: OSI Approved :: Apache Software License
13
12
  Classifier: Operating System :: OS Independent
14
13
  Classifier: Programming Language :: Python :: 3
15
14
  Classifier: Topic :: Internet :: WWW/HTTP :: Dynamic Content
16
15
  Classifier: Topic :: Internet :: WWW/HTTP :: WSGI
17
16
  Description-Content-Type: text/x-rst
18
17
  License-File: LICENSE.txt
18
+ Dynamic: license-file
19
19
 
20
20
  Fresco, a web micro-framework for Python
21
21
  ========================================
@@ -0,0 +1,58 @@
1
+ fresco/__init__.py,sha256=gy3VchKsKsoWqZFqIbMhgzIjNCeFlcNnTl225TC_8qw,3537
2
+ fresco/cookie.py,sha256=Qnx8yOjU4LUJ1fqi7YvqbhAA01rCsclJGl_fxI68slw,7055
3
+ fresco/core.py,sha256=5sV6dTOhtEgEpMH_4sjoI0ewZYLvAPnRjyTfNkm490Q,27037
4
+ fresco/decorators.py,sha256=JL4MlsJz4RWRAuOCCB3fx3rtd-E1CvwO2MD7bf94yHM,3324
5
+ fresco/defaults.py,sha256=YStD4MPcCtq-fREFoupSaAS0SY8lH1oEnKDONlR86zs,26
6
+ fresco/exceptions.py,sha256=KE-LoYUGnho6KltzkU6cnm9vUiUhAiDIjPqn5ba-YCA,4410
7
+ fresco/middleware.py,sha256=TH1I5NthLDwnOdluOSFpP_9SQQYhYqh-8lGuAXT74dc,4811
8
+ fresco/multidict.py,sha256=lKRpSP1XNghLp2-i5cXPfPQxuoJclHpNkWk91F4GI1o,13152
9
+ fresco/options.py,sha256=xMh23WS6HB7P9ka_S0X3DoGSSvb8ESl1m8Pqb52Mork,17152
10
+ fresco/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
11
+ fresco/request.py,sha256=B3OeD4H_2HrgRbg5HhkjiHZ6JWiXTe98wYdtpLbNBCw,30046
12
+ fresco/requestcontext.py,sha256=_AJ7DMT5vlIO4Uc-WlRsYJdRge4WRO7ygibKImOS0iM,3601
13
+ fresco/response.py,sha256=9RB9f6tgS_voM-MK36vGzWpkpp6JISnbF--F2FsAT7g,37605
14
+ fresco/routeargs.py,sha256=E-LQutqg6AojtagZojF7NeMjFBk9joRNMGo842IMTBk,10598
15
+ fresco/routing.py,sha256=d8Z2QyW-X5W4_7wrG39G7PgzwSgLe-8RvxeBJfoh0L0,61615
16
+ fresco/static.py,sha256=rNQz_8-PVhSGup_w-HycqatLEbFes7VSlnNQ0rz24pU,2529
17
+ fresco/subrequests.py,sha256=fOG9Bd3w9Ova0S3qv5ssxQ_otrSxaFcKG7TOy6CxNCg,11068
18
+ fresco/types.py,sha256=PbXppEcckX4ohU8npteU1mCkHOuXQxrnqxk1RNEFXkE,797
19
+ fresco/tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
20
+ fresco/tests/fixtures.py,sha256=eyo2zPivB3fItDkrJqWnOCvIS_A1q1JEhT4AutAB--o,1871
21
+ fresco/tests/test_cookie.py,sha256=HTLmNCjcPoZDeFnZAzY3lJPeduzgU4mi9C-74eSQCec,2171
22
+ fresco/tests/test_core.py,sha256=-eibrVd8UqPqTvcar54kt24m6_lX3mxXR8L7v-WDrWw,34003
23
+ fresco/tests/test_decorators.py,sha256=VFXHo1gm2jldQXeaEF3NNo5fnpdJ-LXc8-vNymPJKTQ,1480
24
+ fresco/tests/test_exceptions.py,sha256=R0Tn86m33iTKecZ69TgH4CqY9XSFP0FsLMH10O5Jth8,973
25
+ fresco/tests/test_middleware.py,sha256=D_sWfX-w3bhItOm54nB_cuYPGoWopISvZCFIuMX68cU,3137
26
+ fresco/tests/test_multidict.py,sha256=uIa1cu5DMAukX2nLOjTiB12oh0icBeSPfsUnqsu85m0,7577
27
+ fresco/tests/test_options.py,sha256=394MLLTyf4vmfkUyqQ8EGIiTTJsQh7P9M6eta2wgUbw,12764
28
+ fresco/tests/test_request.py,sha256=wGDwxCZMbzyGgQJwM2Nlsf0ogcGenXN3srO8dQEhE24,16777
29
+ fresco/tests/test_requestcontext.py,sha256=t8hm-lzIk85ryb3sdlpVoPQyLDWpCjB86dg8nVG1yRw,3115
30
+ fresco/tests/test_response.py,sha256=PYMEr7aJfHMU3eIkBnGN5I6TpYf0xua2-95aNhU1Y7w,9544
31
+ fresco/tests/test_routeargs.py,sha256=VMWUbrXegTLN9Tx2AcrpbjAAEaxAANzkcy02SmpFOmY,8162
32
+ fresco/tests/test_routing.py,sha256=smRhdbru9mRXd0x_bmawCSZbZV7bR1z-9BRiFB9hOJc,40408
33
+ fresco/tests/test_static.py,sha256=y73dqzE2flpACQ_dvNhDzk_WlvNQfkhYF_8YY4MMGDo,4686
34
+ fresco/tests/test_subrequests.py,sha256=7rluJnw-elXRXfrzvAQvGBHRBU93zwnL827mTxBGd3Y,7909
35
+ fresco/tests/util/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
36
+ fresco/tests/util/form_data.py,sha256=TalOuv4BGM3JNrf14tE47o9wAwZ7jA1CvRDnGJFifno,10570
37
+ fresco/tests/util/test_common.py,sha256=NvKX8KIAUki7b2kDLILWqARbOQmR3XyInLlbcwFEhiU,1117
38
+ fresco/tests/util/test_http.py,sha256=mdHDc-4m9sMNkEgHToIsgFuSSXQzNUcYSehPehYvJYo,10748
39
+ fresco/tests/util/test_security.py,sha256=MtpDDKyDhAeRT766Lt3peOv4Jj55TM1lvJk1_5TKaes,1492
40
+ fresco/tests/util/test_urls.py,sha256=U12T9MlP7zCpf-ufoyaZI5nAswi0xCSBOxHjHB2K_0I,8320
41
+ fresco/tests/util/test_wsgi.py,sha256=VsHUCo8yck_40nsYm-H-M0R8QYEE8JcboeGPbcrzsO0,3038
42
+ fresco/util/__init__.py,sha256=mJkaZzvYgBnxsBAGv8y_P1yzonHqWgw6VF2Zs4rmJEA,7
43
+ fresco/util/cache.py,sha256=0xINmBecCYo3h5-zU_yRyJeWmROygE3pO9w9Y3ZONcs,1661
44
+ fresco/util/common.py,sha256=8lvrjhELvYsUWxu7DZi1OJcUOFk2ILYndNsnaS0IqjM,1258
45
+ fresco/util/contentencodings.py,sha256=cCP-nSlXiBAZWoJdlnrQREi9jYRu8UY327bQdfBNlkg,5527
46
+ fresco/util/file.py,sha256=Vp7qJTo9RouUeHq25ExyBGkGTHuW-9Q7D_0GB54DFe8,1383
47
+ fresco/util/http.py,sha256=hxMKjF6FWvugDvToRqSscDhCD1KdVY1bmV4Unwd_Uhs,22672
48
+ fresco/util/io.py,sha256=xxwDNJOcewY8lAR4Ce3cmB_zlrys8JGsESgwGWE198Y,1289
49
+ fresco/util/object.py,sha256=FjYNfPHzvBqq1rn0Y6As-2AVZ_SZOjH-lrSy4EbYmHY,370
50
+ fresco/util/security.py,sha256=nXEdoCak_2c4OA1L1wGwhZygS22s2fzwR0Kp-DdwKZg,1058
51
+ fresco/util/textproc.py,sha256=e5jLTofKCqdm6_Fy8XOyR43AJr5APtL59Kd8cNA9PrQ,2309
52
+ fresco/util/urls.py,sha256=V6-s2WgeARkEcuzpwqtiM8ebOXe5-mNUKOJ8N9LNBHA,10051
53
+ fresco/util/wsgi.py,sha256=RYw4KeOUjzzPOL_HhEtgLyCngofjMdAT8BTLOSKU6KA,13021
54
+ fresco-3.9.0.dist-info/licenses/LICENSE.txt,sha256=z8d0m5b2O9McPEK1xHG_dWgUBT6EfBDz6wA0F7xSPTA,11358
55
+ fresco-3.9.0.dist-info/METADATA,sha256=wQn0fuVCpyBdudhkG3lu_8azHj5P__kApDRqeYHDs6M,1523
56
+ fresco-3.9.0.dist-info/WHEEL,sha256=wUyA8OaulRlbfwMtmQsvNngGrxQHAvkKcvRmdizlJi0,92
57
+ fresco-3.9.0.dist-info/top_level.txt,sha256=p_1aMce5Shjq9fIfdbB-aN8wCDhjF_iYnn98bUebbII,7
58
+ fresco-3.9.0.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: setuptools (72.1.0)
2
+ Generator: setuptools (80.10.2)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5
 
fresco/typing.py DELETED
@@ -1,11 +0,0 @@
1
- from types import TracebackType
2
- from typing import Any
3
- from typing import Callable
4
- from typing import Dict
5
- from typing import Iterable
6
- from typing import List
7
- from typing import Tuple
8
-
9
- WSGICallable = Callable[[Dict[str, Any], Callable], Iterable[bytes]]
10
- ExcInfoTuple = Tuple[type, BaseException, TracebackType]
11
- HeadersList = List[Tuple[str, str]]
@@ -1,57 +0,0 @@
1
- fresco/__init__.py,sha256=DkBKfTdD88kXZYGi5Pv686Es1twTgZ4fVO3mA2nf0GQ,3520
2
- fresco/cookie.py,sha256=Qnx8yOjU4LUJ1fqi7YvqbhAA01rCsclJGl_fxI68slw,7055
3
- fresco/core.py,sha256=mwYR6UP0zRSjcFlNZf51-otX9EcmvgjEZ7GDVQoQexg,26615
4
- fresco/decorators.py,sha256=84NUpRJ-M7GK6wDl42bmCRSvgoWzCsy1huyvGnSAPPw,3232
5
- fresco/exceptions.py,sha256=KE-LoYUGnho6KltzkU6cnm9vUiUhAiDIjPqn5ba-YCA,4410
6
- fresco/middleware.py,sha256=uCAuOtBnvaVBJGrQa8ecvLkSZ6aSKmWaJqxB8Rv4SsQ,4173
7
- fresco/multidict.py,sha256=0CaNNIcFnZ1hLk3NExhNvjc_BtK4zVB26L9gP_7MeNM,13362
8
- fresco/options.py,sha256=0RzwO1eyCUC70GxKFnCHNKDyZwsKc9Q-AmtlMAnfZ-Q,14004
9
- fresco/request.py,sha256=dC7pMg-4Kxa6PcqaaWFL4JviANQotuBjoKwlxZYywRY,27048
10
- fresco/requestcontext.py,sha256=P-SkKJkKLYVqNiR2zwooRROnSnE2VMj2P2-eD5DW5Qg,3504
11
- fresco/response.py,sha256=ADKHbtAGyhwtaUJxB7m_1nqVdZRKUryebmG4FDUjZVY,37072
12
- fresco/routeargs.py,sha256=dxNlqbQ1FrgIY6OCFzcEMdZ0OVyjlMQdQGLmUJgdPYU,10176
13
- fresco/routing.py,sha256=kTFqJ9Nn9cOHlul-lHqKDurBwqlEO4fg8tertb1jkoI,58709
14
- fresco/static.py,sha256=9SKQ3P1YFTP45Qiic-ycvkpKRvqIURp1XSzPazTmYLI,2513
15
- fresco/subrequests.py,sha256=wFJWLuhVAcei5imYc5NBSCBaHBEm-X4_XswPtK3O4Zw,11081
16
- fresco/types.py,sha256=UHITRMDoS90s2zV2wNpqLFhRWESfaBAMuQnL4c21mqY,106
17
- fresco/typing.py,sha256=jQ1r_wme54J08XZUdmuuW4M8ve-gEhm1Wriwctls3r8,347
18
- fresco/tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
19
- fresco/tests/fixtures.py,sha256=eyo2zPivB3fItDkrJqWnOCvIS_A1q1JEhT4AutAB--o,1871
20
- fresco/tests/test_cookie.py,sha256=HTLmNCjcPoZDeFnZAzY3lJPeduzgU4mi9C-74eSQCec,2171
21
- fresco/tests/test_core.py,sha256=lniN-UslszeRAuWlbBU536LDGTo8Hp2nb8kLebXvim0,34019
22
- fresco/tests/test_decorators.py,sha256=VFXHo1gm2jldQXeaEF3NNo5fnpdJ-LXc8-vNymPJKTQ,1480
23
- fresco/tests/test_exceptions.py,sha256=R0Tn86m33iTKecZ69TgH4CqY9XSFP0FsLMH10O5Jth8,973
24
- fresco/tests/test_middleware.py,sha256=D_sWfX-w3bhItOm54nB_cuYPGoWopISvZCFIuMX68cU,3137
25
- fresco/tests/test_multidict.py,sha256=uDwDYII0dvVxaEyDO85zRTWlIWw3LO3StzYemJVm0E0,7565
26
- fresco/tests/test_options.py,sha256=Zx1tLVLeok8tO3dWua2PyTPZgeWbXFMXtN3FnorBmC8,10998
27
- fresco/tests/test_request.py,sha256=hoANrergrohlAeTbQufDMfIbvYURsPyPjCxOVKz7bVo,16389
28
- fresco/tests/test_requestcontext.py,sha256=t8hm-lzIk85ryb3sdlpVoPQyLDWpCjB86dg8nVG1yRw,3115
29
- fresco/tests/test_response.py,sha256=MrhHIDg81pJlTeEcn2rGtU-i59s1KzEccF81u4Up6xs,8934
30
- fresco/tests/test_routeargs.py,sha256=VMWUbrXegTLN9Tx2AcrpbjAAEaxAANzkcy02SmpFOmY,8162
31
- fresco/tests/test_routing.py,sha256=yfZGon6vKwszFp3pCP2Mtnf3W3u4WdELdvVcgIKHOVU,37890
32
- fresco/tests/test_static.py,sha256=y73dqzE2flpACQ_dvNhDzk_WlvNQfkhYF_8YY4MMGDo,4686
33
- fresco/tests/test_subrequests.py,sha256=7rluJnw-elXRXfrzvAQvGBHRBU93zwnL827mTxBGd3Y,7909
34
- fresco/tests/util/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
35
- fresco/tests/util/form_data.py,sha256=TalOuv4BGM3JNrf14tE47o9wAwZ7jA1CvRDnGJFifno,10570
36
- fresco/tests/util/test_common.py,sha256=NvKX8KIAUki7b2kDLILWqARbOQmR3XyInLlbcwFEhiU,1117
37
- fresco/tests/util/test_http.py,sha256=VYcrxKisRhI19AvuZWLuJGdpZo-IN19y4gDUKwuFy0I,10803
38
- fresco/tests/util/test_security.py,sha256=MtpDDKyDhAeRT766Lt3peOv4Jj55TM1lvJk1_5TKaes,1492
39
- fresco/tests/util/test_urls.py,sha256=xKiE6oq0bB-9u8kNYlMQmeCwuAKr1KLQovB-i24wKVQ,7643
40
- fresco/tests/util/test_wsgi.py,sha256=VsHUCo8yck_40nsYm-H-M0R8QYEE8JcboeGPbcrzsO0,3038
41
- fresco/util/__init__.py,sha256=mJkaZzvYgBnxsBAGv8y_P1yzonHqWgw6VF2Zs4rmJEA,7
42
- fresco/util/cache.py,sha256=EjzF9EzzDw4U4coOykkJEgh_8HMDpwhEbYKBo_TeOZQ,1609
43
- fresco/util/common.py,sha256=8lvrjhELvYsUWxu7DZi1OJcUOFk2ILYndNsnaS0IqjM,1258
44
- fresco/util/contentencodings.py,sha256=cCP-nSlXiBAZWoJdlnrQREi9jYRu8UY327bQdfBNlkg,5527
45
- fresco/util/file.py,sha256=Vp7qJTo9RouUeHq25ExyBGkGTHuW-9Q7D_0GB54DFe8,1383
46
- fresco/util/http.py,sha256=6LSzCxr8avha3rRwsU8kUrkHWnQTuOw49mfi1PSBEgo,22199
47
- fresco/util/io.py,sha256=xxwDNJOcewY8lAR4Ce3cmB_zlrys8JGsESgwGWE198Y,1289
48
- fresco/util/object.py,sha256=FjYNfPHzvBqq1rn0Y6As-2AVZ_SZOjH-lrSy4EbYmHY,370
49
- fresco/util/security.py,sha256=nXEdoCak_2c4OA1L1wGwhZygS22s2fzwR0Kp-DdwKZg,1058
50
- fresco/util/textproc.py,sha256=e5jLTofKCqdm6_Fy8XOyR43AJr5APtL59Kd8cNA9PrQ,2309
51
- fresco/util/urls.py,sha256=aaVovLyXNlVoGviiLN94ImqXf-LTQs_xooEIyi3LBc4,9195
52
- fresco/util/wsgi.py,sha256=2cr2b92RpvPSgS_P46X2mlYepoFg9Qji-V-fzxpSNzw,12971
53
- fresco-3.3.4.dist-info/LICENSE.txt,sha256=z8d0m5b2O9McPEK1xHG_dWgUBT6EfBDz6wA0F7xSPTA,11358
54
- fresco-3.3.4.dist-info/METADATA,sha256=v9NcXIhYp5MqENOecCV7XIsFrg7sC9GdRmIHuS912HI,1549
55
- fresco-3.3.4.dist-info/WHEEL,sha256=R0nc6qTxuoLk7ShA2_Y-UWkN8ZdfDBG2B6Eqpz2WXbs,91
56
- fresco-3.3.4.dist-info/top_level.txt,sha256=p_1aMce5Shjq9fIfdbB-aN8wCDhjF_iYnn98bUebbII,7
57
- fresco-3.3.4.dist-info/RECORD,,