plain 0.65.0__py3-none-any.whl → 0.65.1__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.
plain/CHANGELOG.md CHANGED
@@ -1,5 +1,16 @@
1
1
  # plain changelog
2
2
 
3
+ ## [0.65.1](https://github.com/dropseed/plain/releases/plain@0.65.1) (2025-09-22)
4
+
5
+ ### What's changed
6
+
7
+ - Fixed DisallowedHost exception handling in request span attributes to prevent telemetry errors ([bcc0005](https://github.com/dropseed/plain/commit/bcc000575b))
8
+ - Removed cached property optimization for scheme/host to improve request processing reliability ([3a52690](https://github.com/dropseed/plain/commit/3a52690d47))
9
+
10
+ ### Upgrade instructions
11
+
12
+ - No changes required
13
+
3
14
  ## [0.65.0](https://github.com/dropseed/plain/releases/plain@0.65.0) (2025-09-22)
4
15
 
5
16
  ### What's changed
plain/http/request.py CHANGED
@@ -220,6 +220,8 @@ class HttpRequest:
220
220
  location = str(location)
221
221
  bits = urlsplit(location)
222
222
  if not (bits.scheme and bits.netloc):
223
+ current_scheme_host = f"{self.scheme}://{self.get_host()}"
224
+
223
225
  # Handle the simple, most common case. If the location is absolute
224
226
  # and a scheme or host (netloc) isn't provided, skip an expensive
225
227
  # urljoin() as long as no path segments are '.' or '..'.
@@ -233,17 +235,14 @@ class HttpRequest:
233
235
  # If location starts with '//' but has no netloc, reuse the
234
236
  # schema and netloc from the current request. Strip the double
235
237
  # slashes and continue as if it wasn't specified.
236
- location = self._current_scheme_host + location.removeprefix("//")
238
+ location = current_scheme_host + location.removeprefix("//")
237
239
  else:
238
240
  # Join the constructed URL with the provided location, which
239
241
  # allows the provided location to apply query strings to the
240
242
  # base path.
241
- location = urljoin(self._current_scheme_host + self.path, location)
242
- return iri_to_uri(location)
243
+ location = urljoin(current_scheme_host + self.path, location)
243
244
 
244
- @cached_property
245
- def _current_scheme_host(self):
246
- return f"{self.scheme}://{self.get_host()}"
245
+ return iri_to_uri(location)
247
246
 
248
247
  def _get_scheme(self):
249
248
  """
@@ -4,7 +4,7 @@ import types
4
4
  from opentelemetry import baggage, trace
5
5
  from opentelemetry.semconv.attributes import http_attributes, url_attributes
6
6
 
7
- from plain.exceptions import ImproperlyConfigured
7
+ from plain.exceptions import DisallowedHost, ImproperlyConfigured
8
8
  from plain.logs.utils import log_response
9
9
  from plain.runtime import settings
10
10
  from plain.urls import get_resolver
@@ -78,6 +78,10 @@ class BaseHandler:
78
78
  except KeyError:
79
79
  # Missing required WSGI environment variables (e.g. in tests)
80
80
  pass
81
+ except DisallowedHost:
82
+ # Invalid host header - skip URL_FULL for telemetry but let the
83
+ # exception be handled normally by middleware for proper 400 response
84
+ pass
81
85
 
82
86
  # Add query string if present
83
87
  if query_string := request.meta.get("QUERY_STRING"):
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: plain
3
- Version: 0.65.0
3
+ Version: 0.65.1
4
4
  Summary: A web framework for building products with Python.
5
5
  Author-email: Dave Gaeddert <dave.gaeddert@dropseed.dev>
6
6
  License-File: LICENSE
@@ -1,5 +1,5 @@
1
1
  plain/AGENTS.md,sha256=5XMGBpJgbCNIpp60DPXB7bpAtFk8FAzqiZke95T965o,1038
2
- plain/CHANGELOG.md,sha256=VksQqN6aUmaBpAwFEeYBcjbOSWR-LwwWHB8kJmqK3fU,14815
2
+ plain/CHANGELOG.md,sha256=NlQC7IqcrH9tiUMqkCgyG6Pn7xQiaDUE3Xtfn6g4nIc,15292
3
3
  plain/README.md,sha256=5BJyKhf0TDanWVbOQyZ3zsi5Lov9xk-LlJYCDWofM6Y,4078
4
4
  plain/__main__.py,sha256=GK39854Lc_LO_JP8DzY9Y2MIQ4cQEl7SXFJy244-lC8,110
5
5
  plain/debug.py,sha256=XdjnXcbPGsi0J2SpHGaLthhYU5AjhBlkHdemaP4sbYY,758
@@ -59,7 +59,7 @@ plain/http/__init__.py,sha256=PfmXBIq7onLO_bbOrVdj5rJeHxqJMYqrIobVKupUzUA,1003
59
59
  plain/http/cookie.py,sha256=THd7nOl-2ugeBPKgOhbD87aM2oxUbNH8HWrarUn0fpM,1955
60
60
  plain/http/hosts.py,sha256=GbvFzle2VgPC2ehtXW8MM_1XD9gKuv7h-8HTOX3RiJA,4567
61
61
  plain/http/multipartparser.py,sha256=Z1dFJNAd8N5RHUuF67jh1jBfZOFepORsre_3ee6CgOQ,27266
62
- plain/http/request.py,sha256=ikDCo5WOSKgHvDz8jn_CaFNa8grVxhWrR60lROLjRwI,24672
62
+ plain/http/request.py,sha256=6kimxbIZMK2ckx366fQHDzrNTf6H8ih6YJ4y9yx2aAI,24623
63
63
  plain/http/response.py,sha256=FM3otFkKEEkAaV_pVB3JUSMhMk7x_zf5JcDWKhOKviM,23223
64
64
  plain/internal/__init__.py,sha256=fVBaYLCXEQc-7riHMSlw3vMTTuF7-0Bj2I8aGzv0o0w,171
65
65
  plain/internal/files/__init__.py,sha256=VctFgox4Q1AWF3klPaoCC5GIw5KeLafYjY5JmN8mAVw,63
@@ -71,7 +71,7 @@ plain/internal/files/uploadedfile.py,sha256=JRB7T3quQjg-1y3l1ASPxywtSQZhaeMc45uF
71
71
  plain/internal/files/uploadhandler.py,sha256=63_QUwAwfq3bevw79i0S7zt2EB2UBoO7MaauvezaVMY,7198
72
72
  plain/internal/files/utils.py,sha256=xN4HTJXDRdcoNyrL1dFd528MBwodRlHZM8DGTD_oBIg,2646
73
73
  plain/internal/handlers/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
74
- plain/internal/handlers/base.py,sha256=ur-nYmpvXjXhu03aPP1KV5GSNaLL_QZoT8x0v8l6_wg,6006
74
+ plain/internal/handlers/base.py,sha256=rrPq-LqMOsDUP2IQ-d_FUNq8fZfYqbLVMYOeqrftoXQ,6228
75
75
  plain/internal/handlers/exception.py,sha256=TbPYtgZ7ITJahUKhQWkptHK28Lb4zh_nOviNctC2EYs,4815
76
76
  plain/internal/handlers/wsgi.py,sha256=dgPT29t_F9llB-c5RYU3SHxGuZNaZ83xRjOfuOmtOl8,8209
77
77
  plain/internal/middleware/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -161,8 +161,8 @@ plain/views/forms.py,sha256=ESZOXuo6IeYixp1RZvPb94KplkowRiwO2eGJCM6zJI0,2400
161
161
  plain/views/objects.py,sha256=v3Vgvdoc1s0QW6JNWWrO5XXy9zF7vgwndgxX1eOSQoE,4999
162
162
  plain/views/redirect.py,sha256=Xpb3cB7nZYvKgkNqcAxf9Jwm2SWcQ0u2xz4oO5M3vP8,1909
163
163
  plain/views/templates.py,sha256=oAlebEyfES0rzBhfyEJzFmgLkpkbleA6Eip-8zDp-yk,1863
164
- plain-0.65.0.dist-info/METADATA,sha256=L7dFhqvEh4ZVoSDn3ow2O751k6Rx4R_BCWv4I7__ZJw,4488
165
- plain-0.65.0.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
166
- plain-0.65.0.dist-info/entry_points.txt,sha256=iGx7EijzXy87htbSv90RhtAcjhSTH_kvE8aeRCn1TRA,129
167
- plain-0.65.0.dist-info/licenses/LICENSE,sha256=m0D5O7QoH9l5Vz_rrX_9r-C8d9UNr_ciK6Qwac7o6yo,3175
168
- plain-0.65.0.dist-info/RECORD,,
164
+ plain-0.65.1.dist-info/METADATA,sha256=MnXWc7Ncpu8r1geVUL6uiAorVD_1aJ0CJ5KcUs4jkQI,4488
165
+ plain-0.65.1.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
166
+ plain-0.65.1.dist-info/entry_points.txt,sha256=iGx7EijzXy87htbSv90RhtAcjhSTH_kvE8aeRCn1TRA,129
167
+ plain-0.65.1.dist-info/licenses/LICENSE,sha256=m0D5O7QoH9l5Vz_rrX_9r-C8d9UNr_ciK6Qwac7o6yo,3175
168
+ plain-0.65.1.dist-info/RECORD,,
File without changes