fresco 3.7.0__py3-none-any.whl → 3.8.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.

Potentially problematic release.


This version of fresco might be problematic. Click here for more details.

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.7.0"
71
+ __version__ = "3.8.0"
72
72
  __all__ = [
73
73
  "Request",
74
74
  "currentrequest",
fresco/core.py CHANGED
@@ -280,7 +280,9 @@ class FrescoApp(RouteCollection):
280
280
  except ResponseException as e:
281
281
  response = e.response
282
282
  else:
283
- response = self.get_response(request, path, request.method)
283
+ response = self.get_response(
284
+ request, path, request.environ["REQUEST_METHOD"]
285
+ )
284
286
 
285
287
  for f in self.process_response_handlers:
286
288
  try:
fresco/options.py CHANGED
@@ -285,11 +285,15 @@ class Options(dict):
285
285
  )
286
286
  )
287
287
 
288
- if strict and existing_keys and set(self.keys()) != existing_keys:
289
- raise AssertionError(
288
+ if existing_keys and set(self.keys()) != existing_keys:
289
+ error_msg = (
290
290
  f"settings file {path} created undefined options: "
291
291
  f"{set(self.keys()) - existing_keys}"
292
292
  )
293
+ if strict:
294
+ raise AssertionError(error_msg)
295
+ else:
296
+ logger.warning(error_msg)
293
297
 
294
298
  if use_environ:
295
299
  self |= {
fresco/response.py CHANGED
@@ -277,7 +277,7 @@ def encoder(stream, charset):
277
277
 
278
278
 
279
279
  def make_header_name(name):
280
- """\
280
+ """
281
281
  Return a formatted header name from a python idenfier.
282
282
 
283
283
  Example usage::
@@ -677,8 +677,10 @@ class Response(object):
677
677
  newheaders.append((k, v))
678
678
  return self.replace(headers=newheaders + [("Vary", ", ".join(_vary_on))])
679
679
 
680
- def replace(self, content=None, status=None, headers=None, **kwheaders):
681
- """\
680
+ def replace(
681
+ self, content=None, status=None, headers=None, **kwheaders
682
+ ) -> "Response":
683
+ """
682
684
  Return a new response object with any of content, status or headers
683
685
  changed.
684
686
 
@@ -758,7 +760,7 @@ class Response(object):
758
760
  return default_charset
759
761
 
760
762
  @classmethod
761
- def not_found(cls, request=None):
763
+ def not_found(cls, request=None) -> "Response":
762
764
  """
763
765
  Return an HTTP not found response (404).
764
766
 
@@ -781,7 +783,7 @@ class Response(object):
781
783
  )
782
784
 
783
785
  @classmethod
784
- def error(cls, message="500 Internal Server Error"):
786
+ def error(cls, message="500 Internal Server Error") -> "Response":
785
787
  """
786
788
  Return an HTTP server error response (500).
787
789
 
@@ -803,7 +805,7 @@ class Response(object):
803
805
  )
804
806
 
805
807
  @classmethod
806
- def unauthorized(cls, authenticate):
808
+ def unauthorized(cls, authenticate) -> "Response":
807
809
  """
808
810
  Return an HTTP unauthorized response (401)
809
811
  """
@@ -818,7 +820,7 @@ class Response(object):
818
820
  )
819
821
 
820
822
  @classmethod
821
- def unauthorized_basic(cls, realm):
823
+ def unauthorized_basic(cls, realm) -> "Response":
822
824
  """
823
825
  Return an HTTP unauthorized response (401) with a WWW-Authenticate
824
826
  header set for HTTP Basic authentication..
@@ -826,7 +828,7 @@ class Response(object):
826
828
  return cls.unauthorized(authenticate=f'Basic realm="{realm}"')
827
829
 
828
830
  @classmethod
829
- def forbidden(cls, message="Sorry, access is denied"):
831
+ def forbidden(cls, message="Sorry, access is denied") -> "Response":
830
832
  """
831
833
  Return an HTTP forbidden response (403).
832
834
 
@@ -842,7 +844,9 @@ class Response(object):
842
844
  )
843
845
 
844
846
  @classmethod
845
- def bad_request(cls, request=None):
847
+ def bad_request(
848
+ cls, message="The server could not understand your request", request=None
849
+ ) -> "Response":
846
850
  """
847
851
  Return an HTTP bad request response.
848
852
 
@@ -856,16 +860,17 @@ class Response(object):
856
860
  return cls(
857
861
  status=STATUS_BAD_REQUEST,
858
862
  content=[
859
- "<html>"
860
- "<body>"
861
- "<h1>The server could not understand your request</h1>"
862
- "</body>"
863
- "</html>"
863
+ f"<html>"
864
+ f"<body>"
865
+ f"<h1>Bad request</h1>"
866
+ f"<p>{message}</p>"
867
+ f"</body>"
868
+ f"</html>"
864
869
  ],
865
870
  )
866
871
 
867
872
  @classmethod
868
- def length_required(cls, request=None):
873
+ def length_required(cls, request=None) -> "Response":
869
874
  """
870
875
  Return an HTTP Length Required response (411).
871
876
 
@@ -888,7 +893,7 @@ class Response(object):
888
893
  )
889
894
 
890
895
  @classmethod
891
- def payload_too_large(cls, request=None):
896
+ def payload_too_large(cls, request=None) -> "Response":
892
897
  """
893
898
  Return an HTTP Payload Too Large response (413)::
894
899
 
@@ -903,7 +908,7 @@ class Response(object):
903
908
  request_entity_too_large = payload_too_large
904
909
 
905
910
  @classmethod
906
- def method_not_allowed(cls, valid_methods):
911
+ def method_not_allowed(cls, valid_methods) -> "Response":
907
912
  """
908
913
  Return an HTTP method not allowed response (405)::
909
914
 
@@ -925,7 +930,7 @@ class Response(object):
925
930
  )
926
931
 
927
932
  @classmethod
928
- def internal_server_error(cls):
933
+ def internal_server_error(cls) -> "Response":
929
934
  """
930
935
  Return an HTTP internal server error response (500).
931
936
 
@@ -946,7 +951,7 @@ class Response(object):
946
951
  @classmethod
947
952
  def unrestricted_redirect(
948
953
  cls, location, request=None, status=STATUS_FOUND, **kwargs
949
- ):
954
+ ) -> "Response":
950
955
  """
951
956
  Return an HTTP redirect reponse (30x).
952
957
 
@@ -1004,7 +1009,7 @@ class Response(object):
1004
1009
  request = fresco.context.request
1005
1010
  location = request.resolve_url(location)
1006
1011
 
1007
- return Response(
1012
+ return cls(
1008
1013
  "<html><head></head><body>\n"
1009
1014
  "<h1>Page has moved</h1>\n"
1010
1015
  "<p><a href='%s'>%s</a></p>\n"
@@ -1014,8 +1019,8 @@ class Response(object):
1014
1019
  )
1015
1020
 
1016
1021
  @classmethod
1017
- def unrestricted_redirect_permanent(cls, *args, **kwargs):
1018
- """\
1022
+ def unrestricted_redirect_permanent(cls, *args, **kwargs) -> "Response":
1023
+ """
1019
1024
  Return an HTTP permanent redirect reponse.
1020
1025
 
1021
1026
  :param location: the URI of the new location. If relative this will be
@@ -1027,8 +1032,8 @@ class Response(object):
1027
1032
  return cls.unrestricted_redirect(*args, **kwargs)
1028
1033
 
1029
1034
  @classmethod
1030
- def unrestricted_redirect_temporary(cls, *args, **kwargs):
1031
- """\
1035
+ def unrestricted_redirect_temporary(cls, *args, **kwargs) -> "Response":
1036
+ """
1032
1037
  Return an HTTP permanent redirect reponse.
1033
1038
 
1034
1039
  :param location: the URI of the new location. If relative this will be
@@ -1048,7 +1053,7 @@ class Response(object):
1048
1053
  _is_safe_url=is_safe_url,
1049
1054
  allowed_hosts=frozenset(),
1050
1055
  **kwargs,
1051
- ):
1056
+ ) -> "Response":
1052
1057
  """
1053
1058
  Return an HTTP redirect reponse (30x). Will only redirect to the
1054
1059
  current host or hosts in the ``allowed_hosts`` list. A ``ValueError``
@@ -1075,19 +1080,22 @@ class Response(object):
1075
1080
  """
1076
1081
  # Create the fallback redirect response always so that
1077
1082
  # changes to route names don't result in latent bugs
1083
+ fallback_response = None
1078
1084
  if fallback:
1079
- fallback = Response.unrestricted_redirect(fallback, status=status, **kwargs)
1085
+ fallback_response = cls.unrestricted_redirect(
1086
+ fallback, status=status, **kwargs
1087
+ )
1080
1088
  if callable(url) or "//" not in url:
1081
1089
  return cls.unrestricted_redirect(url, status=status, **kwargs)
1082
1090
 
1083
1091
  if url and _is_safe_url(url, allowed_hosts):
1084
1092
  return cls.unrestricted_redirect(url, status=status, **kwargs)
1085
- if fallback:
1086
- return fallback
1093
+ if fallback_response:
1094
+ return fallback_response
1087
1095
  raise ValueError("Unsafe URL")
1088
1096
 
1089
1097
  @classmethod
1090
- def redirect_permanent(cls, *args, **kwargs):
1098
+ def redirect_permanent(cls, *args, **kwargs) -> "Response":
1091
1099
  """
1092
1100
  Return an HTTP permanent redirect reponse.
1093
1101
 
@@ -1100,7 +1108,7 @@ class Response(object):
1100
1108
  return cls.redirect(*args, **kwargs)
1101
1109
 
1102
1110
  @classmethod
1103
- def redirect_temporary(cls, *args, **kwargs):
1111
+ def redirect_temporary(cls, *args, **kwargs) -> "Response":
1104
1112
  """
1105
1113
  Return an HTTP permanent redirect reponse.
1106
1114
 
@@ -1113,7 +1121,7 @@ class Response(object):
1113
1121
  return cls.redirect(*args, **kwargs)
1114
1122
 
1115
1123
  @classmethod
1116
- def meta_refresh(cls, location, delay=1, request=None):
1124
+ def meta_refresh(cls, location, delay=1, request=None) -> "Response":
1117
1125
  """
1118
1126
  Return an HTML page containing a <meta http-equiv="refresh"> tag,
1119
1127
  causing the browser to redirect to the given location after ``delay``
@@ -1152,7 +1160,7 @@ class Response(object):
1152
1160
  headers=None,
1153
1161
  dumps=stdlib_json.dumps,
1154
1162
  **kwargs,
1155
- ):
1163
+ ) -> "Response":
1156
1164
  """
1157
1165
  Return an ``application/json`` response with the given data
1158
1166
  JSON serialized
fresco/routing.py CHANGED
@@ -21,6 +21,7 @@ from collections import defaultdict
21
21
  from collections import namedtuple
22
22
  from collections.abc import Collection
23
23
  from collections.abc import MutableSequence
24
+ from collections.abc import Sequence
24
25
  from importlib import import_module
25
26
  from functools import partial
26
27
  from typing import Any
@@ -732,11 +733,11 @@ class Route(object):
732
733
  view: Optional[Union[ViewCallable, "RouteCollection", str]] = None,
733
734
  kwargs: Optional[dict[str, Any]] = None,
734
735
  args=None,
735
- name=None,
736
+ name: Optional[str] = None,
736
737
  predicate=None,
737
738
  decorators=None,
738
739
  filters=None,
739
- fallthrough_on=None,
740
+ fallthrough_on: Optional[Sequence[int]] = None,
740
741
  provide_request: Optional[bool] = None,
741
742
  **_kwargs: ViewCallable,
742
743
  ):
@@ -885,7 +886,7 @@ class Route(object):
885
886
  args or _kwargs.pop("view_args", tuple()) # type: ignore
886
887
  )
887
888
  self.view_kwargs: dict[str, Any] = dict(
888
- kwargs or _kwargs.pop("view_kwargs", {}), **_kwargs # type: ignore
889
+ kwargs or _kwargs.pop("view_kwargs", {}), **_kwargs # type: ignore
889
890
  )
890
891
 
891
892
  for arg in self.view_args:
@@ -1,15 +1,14 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: fresco
3
- Version: 3.7.0
3
+ Version: 3.8.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
@@ -1,18 +1,18 @@
1
- fresco/__init__.py,sha256=Jo5gW2Xce2hmtXhfaXXJR4aBW1KFYb0Murx2JfIo_E8,3537
1
+ fresco/__init__.py,sha256=Fcc15anYF2j6dR-bTWaWikvOzUJmSlrfrFXf-6ugdvc,3537
2
2
  fresco/cookie.py,sha256=Qnx8yOjU4LUJ1fqi7YvqbhAA01rCsclJGl_fxI68slw,7055
3
- fresco/core.py,sha256=bqGDgm4OH46j6HqnC5nJyn9n1dQw-I1ntUY8dIpeO_M,26988
3
+ fresco/core.py,sha256=5sV6dTOhtEgEpMH_4sjoI0ewZYLvAPnRjyTfNkm490Q,27037
4
4
  fresco/decorators.py,sha256=JL4MlsJz4RWRAuOCCB3fx3rtd-E1CvwO2MD7bf94yHM,3324
5
5
  fresco/defaults.py,sha256=YStD4MPcCtq-fREFoupSaAS0SY8lH1oEnKDONlR86zs,26
6
6
  fresco/exceptions.py,sha256=KE-LoYUGnho6KltzkU6cnm9vUiUhAiDIjPqn5ba-YCA,4410
7
7
  fresco/middleware.py,sha256=TH1I5NthLDwnOdluOSFpP_9SQQYhYqh-8lGuAXT74dc,4811
8
8
  fresco/multidict.py,sha256=lKRpSP1XNghLp2-i5cXPfPQxuoJclHpNkWk91F4GI1o,13152
9
- fresco/options.py,sha256=X66xZV45vWIyQR2GwFTLgV2QGoXOfLhHURWQ_edoxmY,17024
9
+ fresco/options.py,sha256=xMh23WS6HB7P9ka_S0X3DoGSSvb8ESl1m8Pqb52Mork,17152
10
10
  fresco/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
11
11
  fresco/request.py,sha256=XJ9SJAe9zILfWt-YB4zxjIrjECrLYzyxjZ9xk8h4tAw,30024
12
12
  fresco/requestcontext.py,sha256=_AJ7DMT5vlIO4Uc-WlRsYJdRge4WRO7ygibKImOS0iM,3601
13
- fresco/response.py,sha256=ilJ_Wbp7LVP1E6bXp0iAy1o6D0hboXtpLvm2ZCmUGmk,37277
13
+ fresco/response.py,sha256=63zHJSZy2aFB9yImwJmHZ1GwYRdvA_U1mE3yQpscrKE,37711
14
14
  fresco/routeargs.py,sha256=E-LQutqg6AojtagZojF7NeMjFBk9joRNMGo842IMTBk,10598
15
- fresco/routing.py,sha256=r_vPD1xc7brOrbw1iO0X2IP7WX5wlIWlcXwcNndU1ZY,61259
15
+ fresco/routing.py,sha256=k7kRPYYYg6x_b_z5J77PnDJnPfZoVhLRoIfgBxlDLxA,61339
16
16
  fresco/static.py,sha256=rNQz_8-PVhSGup_w-HycqatLEbFes7VSlnNQ0rz24pU,2529
17
17
  fresco/subrequests.py,sha256=fOG9Bd3w9Ova0S3qv5ssxQ_otrSxaFcKG7TOy6CxNCg,11068
18
18
  fresco/types.py,sha256=PbXppEcckX4ohU8npteU1mCkHOuXQxrnqxk1RNEFXkE,797
@@ -51,8 +51,8 @@ fresco/util/security.py,sha256=nXEdoCak_2c4OA1L1wGwhZygS22s2fzwR0Kp-DdwKZg,1058
51
51
  fresco/util/textproc.py,sha256=e5jLTofKCqdm6_Fy8XOyR43AJr5APtL59Kd8cNA9PrQ,2309
52
52
  fresco/util/urls.py,sha256=V6-s2WgeARkEcuzpwqtiM8ebOXe5-mNUKOJ8N9LNBHA,10051
53
53
  fresco/util/wsgi.py,sha256=RYw4KeOUjzzPOL_HhEtgLyCngofjMdAT8BTLOSKU6KA,13021
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,,
54
+ fresco-3.8.0.dist-info/licenses/LICENSE.txt,sha256=z8d0m5b2O9McPEK1xHG_dWgUBT6EfBDz6wA0F7xSPTA,11358
55
+ fresco-3.8.0.dist-info/METADATA,sha256=_EHQUpLmItoT9bDqEuuzfXbofdMjSQfnivFCrGjNlF4,1523
56
+ fresco-3.8.0.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
57
+ fresco-3.8.0.dist-info/top_level.txt,sha256=p_1aMce5Shjq9fIfdbB-aN8wCDhjF_iYnn98bUebbII,7
58
+ fresco-3.8.0.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: setuptools (80.3.1)
2
+ Generator: setuptools (80.9.0)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5