plain 0.43.1__py3-none-any.whl → 0.44.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.
plain/README.md CHANGED
@@ -31,7 +31,7 @@ The `plain` package includes everything you need to start handling web requests
31
31
  - [plain.cache](/plain-cache/plain/cache/README.md) - A database-driven general purpose cache.
32
32
  - [plain.email](/plain-email/plain/email/README.md) - Send emails with SMTP or custom backends.
33
33
  - [plain.sessions](/plain-sessions/plain/sessions/README.md) - User sessions and cookies.
34
- - [plain.worker](/plain-worker/plain/worker/README.md) - Backgrounb jobs stored in the database.
34
+ - [plain.worker](/plain-worker/plain/worker/README.md) - Background jobs stored in the database.
35
35
  - [plain.api](/plain-api/plain/api/README.md) - Build APIs with Plain views.
36
36
 
37
37
  ## Auth Packages
plain/csrf/middleware.py CHANGED
@@ -8,6 +8,7 @@ against request forgeries from other sites.
8
8
  import logging
9
9
  import string
10
10
  from collections import defaultdict
11
+ from functools import cached_property
11
12
  from urllib.parse import urlparse
12
13
 
13
14
  from plain.exceptions import DisallowedHost
@@ -16,7 +17,6 @@ from plain.logs import log_response
16
17
  from plain.runtime import settings
17
18
  from plain.utils.cache import patch_vary_headers
18
19
  from plain.utils.crypto import constant_time_compare, get_random_string
19
- from plain.utils.functional import cached_property
20
20
  from plain.utils.http import is_same_domain
21
21
  from plain.utils.regex_helper import _lazy_re_compile
22
22
 
plain/forms/forms.py CHANGED
@@ -3,9 +3,9 @@ Form classes
3
3
  """
4
4
 
5
5
  import copy
6
+ from functools import cached_property
6
7
 
7
8
  from plain.exceptions import NON_FIELD_ERRORS
8
- from plain.utils.functional import cached_property
9
9
 
10
10
  from .exceptions import ValidationError
11
11
  from .fields import Field, FileField
plain/http/request.py CHANGED
@@ -2,6 +2,7 @@ import codecs
2
2
  import copy
3
3
  import json
4
4
  import uuid
5
+ from functools import cached_property
5
6
  from io import BytesIO
6
7
  from itertools import chain
7
8
  from urllib.parse import parse_qsl, quote, urlencode, urljoin, urlsplit
@@ -25,7 +26,6 @@ from plain.utils.datastructures import (
25
26
  MultiValueDict,
26
27
  )
27
28
  from plain.utils.encoding import iri_to_uri
28
- from plain.utils.functional import cached_property
29
29
  from plain.utils.http import is_same_domain, parse_header_parameters
30
30
  from plain.utils.regex_helper import _lazy_re_compile
31
31
 
plain/http/response.py CHANGED
@@ -18,7 +18,7 @@ from plain.json import PlainJSONEncoder
18
18
  from plain.runtime import settings
19
19
  from plain.utils import timezone
20
20
  from plain.utils.datastructures import CaseInsensitiveMapping
21
- from plain.utils.encoding import iri_to_uri
21
+ from plain.utils.encoding import force_bytes, iri_to_uri
22
22
  from plain.utils.http import content_disposition_header, http_date
23
23
  from plain.utils.regex_helper import _lazy_re_compile
24
24
 
@@ -258,7 +258,17 @@ class ResponseBase:
258
258
  self.cookies[key]["samesite"] = samesite
259
259
 
260
260
  def set_signed_cookie(self, key, value, salt="", **kwargs):
261
- value = signing.get_cookie_signer(salt=key + salt).sign(value)
261
+ """Set a cookie signed with the SECRET_KEY."""
262
+
263
+ def _cookie_key(k):
264
+ return b"plain.http.cookies" + force_bytes(k)
265
+
266
+ signer = signing.TimestampSigner(
267
+ key=_cookie_key(settings.SECRET_KEY),
268
+ fallback_keys=map(_cookie_key, settings.SECRET_KEY_FALLBACKS),
269
+ salt=key + salt,
270
+ )
271
+ value = signer.sign(value)
262
272
  return self.set_cookie(key, value, **kwargs)
263
273
 
264
274
  def delete_cookie(self, key, path="/", domain=None, samesite=None):
@@ -1,8 +1,8 @@
1
1
  import os
2
+ from functools import cached_property
2
3
  from io import UnsupportedOperation
3
4
 
4
5
  from plain.internal.files.utils import FileProxyMixin
5
- from plain.utils.functional import cached_property
6
6
 
7
7
 
8
8
  class File(FileProxyMixin):
@@ -1,11 +1,11 @@
1
1
  import uuid
2
+ from functools import cached_property
2
3
  from io import IOBase
3
4
  from urllib.parse import quote
4
5
 
5
6
  from plain import signals
6
7
  from plain.http import HttpRequest, QueryDict, parse_cookie
7
8
  from plain.internal.handlers import base
8
- from plain.utils.functional import cached_property
9
9
  from plain.utils.regex_helper import _lazy_re_compile
10
10
 
11
11
  _slashes_re = _lazy_re_compile(rb"/+")
@@ -125,15 +125,13 @@ class WSGIRequest(HttpRequest):
125
125
 
126
126
 
127
127
  class WSGIHandler(base.BaseHandler):
128
- request_class = WSGIRequest
129
-
130
128
  def __init__(self, *args, **kwargs):
131
129
  super().__init__(*args, **kwargs)
132
130
  self.load_middleware()
133
131
 
134
132
  def __call__(self, environ, start_response):
135
133
  signals.request_started.send(sender=self.__class__, environ=environ)
136
- request = self.request_class(environ)
134
+ request = WSGIRequest(environ)
137
135
  response = self.get_response(request)
138
136
 
139
137
  response._handler_class = self.__class__
plain/paginator.py CHANGED
@@ -1,9 +1,9 @@
1
1
  import collections.abc
2
2
  import inspect
3
3
  import warnings
4
+ from functools import cached_property
4
5
  from math import ceil
5
6
 
6
- from plain.utils.functional import cached_property
7
7
  from plain.utils.inspect import method_has_no_args
8
8
 
9
9
 
@@ -109,12 +109,6 @@ HTTP_ERROR_VIEWS: dict[int] = {}
109
109
  # phase the middleware will be applied in reverse order.
110
110
  MIDDLEWARE: list[str] = []
111
111
 
112
- ###########
113
- # SIGNING #
114
- ###########
115
-
116
- COOKIE_SIGNING_BACKEND = "plain.signing.TimestampSigner"
117
-
118
112
  ########
119
113
  # CSRF #
120
114
  ########
@@ -121,7 +121,9 @@ class Settings:
121
121
  if setting in self._settings:
122
122
  setting_def = self._settings[setting]
123
123
  try:
124
- parsed_value = _parse_env_value(value, setting_def.annotation)
124
+ parsed_value = _parse_env_value(
125
+ value, setting_def.annotation, setting
126
+ )
125
127
  setting_def.set_value(parsed_value, "env")
126
128
  except ImproperlyConfigured as e:
127
129
  self._errors.append(str(e))
@@ -211,9 +213,11 @@ class Settings:
211
213
  return f'<Settings "{self._settings_module}">'
212
214
 
213
215
 
214
- def _parse_env_value(value, annotation):
216
+ def _parse_env_value(value, annotation, setting_name):
215
217
  if not annotation:
216
- raise ImproperlyConfigured("Type hint required to set from environment.")
218
+ raise ImproperlyConfigured(
219
+ f"{setting_name}: Type hint required to set from environment."
220
+ )
217
221
 
218
222
  if annotation is bool:
219
223
  # Special case for bools
@@ -226,7 +230,7 @@ def _parse_env_value(value, annotation):
226
230
  return json.loads(value)
227
231
  except json.JSONDecodeError as e:
228
232
  raise ImproperlyConfigured(
229
- f"Invalid JSON value for setting: {e.msg}"
233
+ f"Invalid JSON value for setting '{setting_name}': {e.msg}"
230
234
  ) from e
231
235
 
232
236
 
plain/signing.py CHANGED
@@ -41,8 +41,6 @@ import zlib
41
41
 
42
42
  from plain.runtime import settings
43
43
  from plain.utils.crypto import constant_time_compare, salted_hmac
44
- from plain.utils.encoding import force_bytes
45
- from plain.utils.module_loading import import_string
46
44
  from plain.utils.regex_helper import _lazy_re_compile
47
45
 
48
46
  _SEP_UNSAFE = _lazy_re_compile(r"^[A-z0-9-_=]*$")
@@ -101,20 +99,6 @@ def base64_hmac(salt, value, key, algorithm="sha1"):
101
99
  ).decode()
102
100
 
103
101
 
104
- def _cookie_signer_key(key):
105
- # SECRET_KEYS items may be str or bytes.
106
- return b"plain.http.cookies" + force_bytes(key)
107
-
108
-
109
- def get_cookie_signer(salt="plain.signing.get_cookie_signer"):
110
- Signer = import_string(settings.COOKIE_SIGNING_BACKEND)
111
- return Signer(
112
- key=_cookie_signer_key(settings.SECRET_KEY),
113
- fallback_keys=map(_cookie_signer_key, settings.SECRET_KEY_FALLBACKS),
114
- salt=salt,
115
- )
116
-
117
-
118
102
  class JSONSerializer:
119
103
  """
120
104
  Simple wrapper around json to be used in signing.dumps and
plain/utils/connection.py CHANGED
@@ -1,7 +1,7 @@
1
+ from functools import cached_property
1
2
  from threading import local
2
3
 
3
4
  from plain.runtime import settings as plain_settings
4
- from plain.utils.functional import cached_property
5
5
 
6
6
 
7
7
  class ConnectionProxy:
plain/utils/functional.py CHANGED
@@ -4,49 +4,6 @@ import operator
4
4
  from functools import total_ordering, wraps
5
5
 
6
6
 
7
- class cached_property:
8
- """
9
- Decorator that converts a method with a single self argument into a
10
- property cached on the instance.
11
-
12
- A cached property can be made out of an existing method:
13
- (e.g. ``url = cached_property(get_absolute_url)``).
14
- """
15
-
16
- name = None
17
-
18
- @staticmethod
19
- def func(instance):
20
- raise TypeError(
21
- "Cannot use cached_property instance without calling __set_name__() on it."
22
- )
23
-
24
- def __init__(self, func):
25
- self.real_func = func
26
- self.__doc__ = getattr(func, "__doc__")
27
-
28
- def __set_name__(self, owner, name):
29
- if self.name is None:
30
- self.name = name
31
- self.func = self.real_func
32
- elif name != self.name:
33
- raise TypeError(
34
- "Cannot assign the same cached_property to two different names "
35
- f"({self.name!r} and {name!r})."
36
- )
37
-
38
- def __get__(self, instance, cls=None):
39
- """
40
- Call the function and put the return value in instance.__dict__ so that
41
- subsequent attribute access on the instance returns the cached value
42
- instead of calling cached_property.__get__().
43
- """
44
- if instance is None:
45
- return self
46
- res = instance.__dict__[self.name] = self.func(instance)
47
- return res
48
-
49
-
50
7
  class classproperty:
51
8
  """
52
9
  Decorator that converts a method with a single cls argument into a property
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: plain
3
- Version: 0.43.1
3
+ Version: 0.44.0
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
@@ -42,7 +42,7 @@ The `plain` package includes everything you need to start handling web requests
42
42
  - [plain.cache](/plain-cache/plain/cache/README.md) - A database-driven general purpose cache.
43
43
  - [plain.email](/plain-email/plain/email/README.md) - Send emails with SMTP or custom backends.
44
44
  - [plain.sessions](/plain-sessions/plain/sessions/README.md) - User sessions and cookies.
45
- - [plain.worker](/plain-worker/plain/worker/README.md) - Backgrounb jobs stored in the database.
45
+ - [plain.worker](/plain-worker/plain/worker/README.md) - Background jobs stored in the database.
46
46
  - [plain.api](/plain-api/plain/api/README.md) - Build APIs with Plain views.
47
47
 
48
48
  ## Auth Packages
@@ -1,10 +1,10 @@
1
- plain/README.md,sha256=TV_cAASLTSFjlmW7LD8J8Md1iKSjZpuZdEQGBCEXGUE,3986
1
+ plain/README.md,sha256=gik6DBZcJAITcm4WRq_L53AxkjY45eQLafyTCSf0CKE,3986
2
2
  plain/__main__.py,sha256=GK39854Lc_LO_JP8DzY9Y2MIQ4cQEl7SXFJy244-lC8,110
3
3
  plain/debug.py,sha256=abPkJY4aSbBYGEYSZST_ZY3ohXPGDdz9uWQBYRqfd3M,730
4
4
  plain/exceptions.py,sha256=Z9cbPE5im_Y-bjVq8cqC85gBoqOr80rLFG5wTKixrwE,5894
5
5
  plain/json.py,sha256=McJdsbMT1sYwkGRG--f2NSZz0hVXPMix9x3nKaaak2o,1262
6
- plain/paginator.py,sha256=-fpLJd6c-V8bLCaNCHfTqPtm-Lm2Y1TuKqFDfy7n3ZE,5857
7
- plain/signing.py,sha256=sf7g1Mp-FzdjFAEoLxHyu2YvbUl5w4FOtTVDAfq6TO0,8733
6
+ plain/paginator.py,sha256=iXiOyt2r_YwNrkqCRlaU7V-M_BKaaQ8XZElUBVa6yeU,5844
7
+ plain/signing.py,sha256=r2KvCOxkrSWCULFxYa9BHYx3L3a2oLq8RDnq_92inTw,8207
8
8
  plain/validators.py,sha256=TePzFHzwR4JXUAZ_Y2vC6mkKgVxHX3QBXI6Oex0rV8c,19236
9
9
  plain/wsgi.py,sha256=R6k5FiAElvGDApEbMPTT0MPqSD7n2e2Az5chQqJZU0I,236
10
10
  plain/assets/README.md,sha256=wgsmBK5vAHgFMZ010q7LTrgLq5BTfuPuuug5HLZ9GNw,3774
@@ -34,23 +34,23 @@ plain/cli/startup.py,sha256=wLaFuyUb4ewWhtehBCGicrRCXIIGCRbeCT3ce9hUv-A,1022
34
34
  plain/cli/urls.py,sha256=CS9NFpwZBWveAR8F3YsoUNySDEK_PwF73oSgLDfkOdI,3776
35
35
  plain/cli/utils.py,sha256=VwlIh0z7XxzVV8I3qM2kZo07fkJFPoeeVZa1ODG616k,258
36
36
  plain/csrf/README.md,sha256=nxCpPk1HF5eAM-7paxg9D-9RVCU9jXsSPAVHkJvA_DU,717
37
- plain/csrf/middleware.py,sha256=MJusxqfa_SVpzHchfkTOCzccCl8twT8Cr_ymxLb5EvY,17414
37
+ plain/csrf/middleware.py,sha256=U3B9R7ciO_UAf7O3jdNtVu6QZ_3Yrm8isRdnW6bVKX4,17401
38
38
  plain/csrf/views.py,sha256=HwQqfI6KPelHP9gSXhjfZaTLQic71PKsoZ6DPhr1rKI,572
39
39
  plain/forms/README.md,sha256=TawBdy1jP0-8HUsfUzd7vvgkwl3EJGejDxFhWR8F-80,2242
40
40
  plain/forms/__init__.py,sha256=UxqPwB8CiYPCQdHmUc59jadqaXqDmXBH8y4bt9vTPms,226
41
41
  plain/forms/boundfield.py,sha256=LhydhCVR0okrli0-QBMjGjAJ8-06gTCXVEaBZhBouQk,1741
42
42
  plain/forms/exceptions.py,sha256=NYk1wjYDkk-lA_XMJQDItOebQcL_m_r2eNRc2mkLQkg,315
43
43
  plain/forms/fields.py,sha256=C71ed7m8VBnsgS-eIC6Xsmz7ruNSkdGa1BuSo7V3QKc,34574
44
- plain/forms/forms.py,sha256=gyDUrl7wh7n3fqKMB6eH0-AvCmWXST3oc-jBWUf9rmU,10454
44
+ plain/forms/forms.py,sha256=hF7Dl8rEaiBTZhFQyfbh1Zf54BSEka8RYpBiGqkTa8I,10441
45
45
  plain/http/README.md,sha256=F9wbahgSU3jIDEG14gJjdPJRem4weUNvwnwhb7o3cu0,722
46
46
  plain/http/__init__.py,sha256=DIsDRbBsCGa4qZgq-fUuQS0kkxfbTU_3KpIM9VvH04w,1067
47
47
  plain/http/cookie.py,sha256=11FnSG3Plo6T3jZDbPoCw7SKh9ExdBio3pTmIO03URg,597
48
48
  plain/http/multipartparser.py,sha256=Z1dFJNAd8N5RHUuF67jh1jBfZOFepORsre_3ee6CgOQ,27266
49
- plain/http/request.py,sha256=Xlolhpp2ZfZIi0TOz960U16CdqGi8jMhmHsBtxpkR_4,25631
50
- plain/http/response.py,sha256=IGSg22ioob6kSRkKGQsQF_exb2Lch8RKiZr_Xoi1_xA,23644
49
+ plain/http/request.py,sha256=DbnC_E-PeiLM9pVJdcO869BtAU2gniLflMnPAOrrKU8,25618
50
+ plain/http/response.py,sha256=WvVxQgQMq9X8YRBa9_neowfP3mx3TzN90SShSulfFQo,23970
51
51
  plain/internal/__init__.py,sha256=fVBaYLCXEQc-7riHMSlw3vMTTuF7-0Bj2I8aGzv0o0w,171
52
52
  plain/internal/files/__init__.py,sha256=VctFgox4Q1AWF3klPaoCC5GIw5KeLafYjY5JmN8mAVw,63
53
- plain/internal/files/base.py,sha256=-JpRMzv2bgVSZ9dcxh13gGRTVeEd_Tjd02iQMOXsRgQ,4126
53
+ plain/internal/files/base.py,sha256=2z19tik2_xgXlI6nfVZ4woSF9WB0RSUzsvOfi1Bz8Wg,4113
54
54
  plain/internal/files/locks.py,sha256=z03q7IZD4tPMK3s1HKF3w_uetkFj6w6FTheLUxZsfB0,3616
55
55
  plain/internal/files/move.py,sha256=jfdD29QhamxZjXRgqmZS4dJoJ4sK6M7QK1Km-69jWeo,3238
56
56
  plain/internal/files/temp.py,sha256=UJJnCI8dqPIC8XXHU3-jG2-0svbkrgGlBs4yhciLm4c,2506
@@ -60,7 +60,7 @@ plain/internal/files/utils.py,sha256=xN4HTJXDRdcoNyrL1dFd528MBwodRlHZM8DGTD_oBIg
60
60
  plain/internal/handlers/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
61
61
  plain/internal/handlers/base.py,sha256=6K8wd5DojOYA-UEQTd1jxdDggm5ThHXQahVcuJqd2qo,4169
62
62
  plain/internal/handlers/exception.py,sha256=vfha_6-fz6S6VYCP1PMBfue2Gw-_th6jqaTE372fGlw,4809
63
- plain/internal/handlers/wsgi.py,sha256=sOgqnE4fNzKD2a5EMubiEpHEK9Mi69FWx3BVWxGgMw0,8262
63
+ plain/internal/handlers/wsgi.py,sha256=dgPT29t_F9llB-c5RYU3SHxGuZNaZ83xRjOfuOmtOl8,8209
64
64
  plain/internal/middleware/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
65
65
  plain/internal/middleware/headers.py,sha256=ENIW1Gwat54hv-ejgp2R8QTZm-PlaI7k44WU01YQrNk,964
66
66
  plain/internal/middleware/https.py,sha256=XpuQK8HicYX1jNanQHqNgyQ9rqe4NLUOZO3ZzKdsP8k,1203
@@ -83,8 +83,8 @@ plain/preflight/security.py,sha256=oxUZBp2M0bpBfUoLYepIxoex2Y90nyjlrL8XU8UTHYY,2
83
83
  plain/preflight/urls.py,sha256=cQ-WnFa_5oztpKdtwhuIGb7pXEml__bHsjs1SWO2YNI,1468
84
84
  plain/runtime/README.md,sha256=S_FIOmSq8LkVQHh9Xm6s3EJWKTVdlSr5A_bNXgh02X8,4740
85
85
  plain/runtime/__init__.py,sha256=0Q7k0V-8OfmTaKC0paNvV4Lx92L1_J7xoEWQH9aO5y4,2005
86
- plain/runtime/global_settings.py,sha256=bg7vnEDGU4mdMKFF7QnnhCFawAUjqqXiocryaOr6gsU,5438
87
- plain/runtime/user_settings.py,sha256=uRHHVfzUvHon91_fOKj7K2WaBYwJ1gCPLfeXqKj5CTs,10902
86
+ plain/runtime/global_settings.py,sha256=MpJ6vtBMO2EYALaKXrtgcGoxLh9Y549zwwErC5D5K7I,5343
87
+ plain/runtime/user_settings.py,sha256=OzMiEkE6ZQ50nxd1WIqirXPiNuMAQULklYHEzgzLWgA,11027
88
88
  plain/signals/README.md,sha256=FInfJXdVQkb7u93PvD8XgPbz_f6m0l2xIu_4PyttV1E,234
89
89
  plain/signals/__init__.py,sha256=eAs0kLqptuP6I31dWXeAqRNji3svplpAV4Ez6ktjwXM,131
90
90
  plain/signals/dispatch/__init__.py,sha256=FzEygqV9HsM6gopio7O2Oh_X230nA4d5Q9s0sUjMq0E,292
@@ -114,7 +114,7 @@ plain/urls/utils.py,sha256=lKxTX_A3XJpIH7FjlNYju108stY6-8Sw2uVdiSsxOKQ,1249
114
114
  plain/utils/README.md,sha256=hRRkcg4CxMX-zz8d4Bn6V2uJr_VKgTLurc1jY7QlEx8,198
115
115
  plain/utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
116
116
  plain/utils/cache.py,sha256=iuvOTIfI1s857iVOAPNLK5lkzlrl0fIiBYaiUXWQu40,5303
117
- plain/utils/connection.py,sha256=NN7xRhy6qIWuOOhi1x9YdGcFcYhKepTiMUETeEMS0vY,2501
117
+ plain/utils/connection.py,sha256=KF57CXt4tVO0EXMRwvIQX0eSruvpNQwGkK4_YGT9nXo,2488
118
118
  plain/utils/crypto.py,sha256=zFDydnaqNMGYFHUc-CAn8f93685a17BhGusAcITH1lI,2662
119
119
  plain/utils/datastructures.py,sha256=g4UYTbxIb_n8F9JWMP4dHPwUz71591fHreGATPO4qEc,10240
120
120
  plain/utils/dateparse.py,sha256=u9_tF85YteXSjW9KQzNg_pcCEFDZS3EGorCddcWU0vE,5351
@@ -122,7 +122,7 @@ plain/utils/deconstruct.py,sha256=7NwEFIDCiadAArUBFmiErzDgfIgDWeKqqQFDXwSgQoQ,18
122
122
  plain/utils/decorators.py,sha256=mLHOo2jLdvYRo2z8lkeVn2vQErlj7xC6XoLwZBYf_z8,358
123
123
  plain/utils/duration.py,sha256=l0Gc41-DeyyAmpdy2XG-YO5UKxMf1NDpWIlQuD5hAn0,1162
124
124
  plain/utils/encoding.py,sha256=T0Shb2xRAR3NPwwoqhpUOB55gDprWzqu72aRiiulv9Y,4251
125
- plain/utils/functional.py,sha256=9sfuPSX1RalDkLNLjR7k-OjooHXjHSWB9ya2kDLOWtE,14652
125
+ plain/utils/functional.py,sha256=eJksrhVdkC8HKF56qtVyTOsOnkZB2jMUnXSTGzjJMF4,13331
126
126
  plain/utils/hashable.py,sha256=uLWobCCh7VcEPJ7xzVGPgigNVuTazYJbyzRzHTCI_wo,739
127
127
  plain/utils/html.py,sha256=SR8oNrungB5gxJaHbvAaCw_bAiqLQOk09fj-iIXY0i0,3679
128
128
  plain/utils/http.py,sha256=VOOnwRXnDp5PL_qEmkInLTm10fF58vlhVjeSTdzV2cQ,6031
@@ -146,8 +146,8 @@ plain/views/forms.py,sha256=ESZOXuo6IeYixp1RZvPb94KplkowRiwO2eGJCM6zJI0,2400
146
146
  plain/views/objects.py,sha256=GGbcfg_9fPZ-PiaBwIHG2e__8GfWDR7JQtQ15wTyiHg,5970
147
147
  plain/views/redirect.py,sha256=daq2cQIkdDF78bt43sjuZxRAyJm_t_SKw6tyPmiXPIc,1985
148
148
  plain/views/templates.py,sha256=SU1fO9gVMp-gEQHYeFplxvmgeMyrLgT8MJ12WNVmQC8,2085
149
- plain-0.43.1.dist-info/METADATA,sha256=6uNFnTLaGGNquLaCjlvqN7vDZThC-YouL3ItOCxaIxE,4297
150
- plain-0.43.1.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
151
- plain-0.43.1.dist-info/entry_points.txt,sha256=1Ys2lsSeMepD1vz8RSrJopna0RQfUd951vYvCRsvl6A,45
152
- plain-0.43.1.dist-info/licenses/LICENSE,sha256=m0D5O7QoH9l5Vz_rrX_9r-C8d9UNr_ciK6Qwac7o6yo,3175
153
- plain-0.43.1.dist-info/RECORD,,
149
+ plain-0.44.0.dist-info/METADATA,sha256=U2-CD6dtM5QQobziqQQmvdLz2EN1XhxghI587wYQSq0,4297
150
+ plain-0.44.0.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
151
+ plain-0.44.0.dist-info/entry_points.txt,sha256=1Ys2lsSeMepD1vz8RSrJopna0RQfUd951vYvCRsvl6A,45
152
+ plain-0.44.0.dist-info/licenses/LICENSE,sha256=m0D5O7QoH9l5Vz_rrX_9r-C8d9UNr_ciK6Qwac7o6yo,3175
153
+ plain-0.44.0.dist-info/RECORD,,
File without changes