plain 0.13.0__py3-none-any.whl → 0.13.2__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/cli/README.md +2 -2
- plain/cli/cli.py +8 -17
- plain/cli/startup.py +2 -2
- plain/csrf/middleware.py +1 -0
- plain/exceptions.py +2 -1
- plain/forms/forms.py +5 -5
- plain/http/multipartparser.py +5 -5
- plain/http/request.py +5 -5
- plain/http/response.py +14 -14
- plain/internal/files/locks.py +1 -0
- plain/internal/files/move.py +1 -2
- plain/internal/files/uploadhandler.py +1 -0
- plain/internal/files/utils.py +3 -3
- plain/internal/handlers/base.py +3 -7
- plain/internal/handlers/exception.py +1 -3
- plain/internal/handlers/wsgi.py +1 -1
- plain/internal/middleware/slash.py +5 -8
- plain/packages/config.py +9 -15
- plain/packages/registry.py +12 -12
- plain/paginator.py +1 -2
- plain/preflight/messages.py +3 -10
- plain/preflight/registry.py +2 -2
- plain/preflight/urls.py +4 -4
- plain/runtime/global_settings.py +1 -0
- plain/signing.py +4 -4
- plain/test/client.py +14 -13
- plain/urls/base.py +1 -1
- plain/urls/conf.py +2 -1
- plain/urls/resolvers.py +20 -33
- plain/utils/cache.py +1 -0
- plain/utils/crypto.py +2 -1
- plain/utils/datastructures.py +2 -2
- plain/utils/dateformat.py +13 -12
- plain/utils/dateparse.py +1 -1
- plain/utils/decorators.py +1 -1
- plain/utils/html.py +7 -7
- plain/utils/http.py +8 -8
- plain/utils/ipv6.py +1 -1
- plain/utils/module_loading.py +2 -2
- plain/utils/regex_helper.py +7 -6
- plain/utils/termcolors.py +4 -4
- plain/utils/text.py +7 -7
- plain/utils/timesince.py +1 -1
- plain/utils/timezone.py +5 -5
- plain/validators.py +1 -3
- plain/views/forms.py +2 -2
- {plain-0.13.0.dist-info → plain-0.13.2.dist-info}/METADATA +7 -12
- {plain-0.13.0.dist-info → plain-0.13.2.dist-info}/RECORD +54 -54
- {plain-0.13.0.dist-info → plain-0.13.2.dist-info}/WHEEL +1 -1
- plain-0.13.2.dist-info/entry_points.txt +2 -0
- plain-0.13.0.dist-info/entry_points.txt +0 -3
- {plain-0.13.0.dist-info → plain-0.13.2.dist-info/licenses}/LICENSE +0 -0
plain/utils/regex_helper.py
CHANGED
@@ -5,6 +5,7 @@ Used internally by Plain and not intended for external use.
|
|
5
5
|
This is not, and is not intended to be, a complete reg-exp decompiler. It
|
6
6
|
should be good enough for a large class of URLS, however.
|
7
7
|
"""
|
8
|
+
|
8
9
|
import re
|
9
10
|
|
10
11
|
from plain.utils.functional import SimpleLazyObject
|
@@ -111,9 +112,9 @@ def normalize(pattern):
|
|
111
112
|
ch, escaped = next(pattern_iter)
|
112
113
|
if ch != "?" or escaped:
|
113
114
|
# A positional group
|
114
|
-
name = "_%d" % num_args
|
115
|
+
name = "_%d" % num_args # noqa: UP031
|
115
116
|
num_args += 1
|
116
|
-
result.append(Group((("
|
117
|
+
result.append(Group(((f"%({name})s"), name)))
|
117
118
|
walk_to_end(ch, pattern_iter)
|
118
119
|
else:
|
119
120
|
ch, escaped = next(pattern_iter)
|
@@ -127,12 +128,12 @@ def normalize(pattern):
|
|
127
128
|
elif ch != "P":
|
128
129
|
# Anything else, other than a named group, is something
|
129
130
|
# we cannot reverse.
|
130
|
-
raise ValueError("Non-reversible reg-exp portion: '(
|
131
|
+
raise ValueError(f"Non-reversible reg-exp portion: '(?{ch}'")
|
131
132
|
else:
|
132
133
|
ch, escaped = next(pattern_iter)
|
133
134
|
if ch not in ("<", "="):
|
134
135
|
raise ValueError(
|
135
|
-
"Non-reversible reg-exp portion: '(?P
|
136
|
+
f"Non-reversible reg-exp portion: '(?P{ch}'"
|
136
137
|
)
|
137
138
|
# We are in a named capturing group. Extra the name and
|
138
139
|
# then skip to the end.
|
@@ -150,10 +151,10 @@ def normalize(pattern):
|
|
150
151
|
# Named backreferences have already consumed the
|
151
152
|
# parenthesis.
|
152
153
|
if terminal_char != ")":
|
153
|
-
result.append(Group((("
|
154
|
+
result.append(Group(((f"%({param})s"), param)))
|
154
155
|
walk_to_end(ch, pattern_iter)
|
155
156
|
else:
|
156
|
-
result.append(Group((("
|
157
|
+
result.append(Group(((f"%({param})s"), None)))
|
157
158
|
elif ch in "*?+{":
|
158
159
|
# Quantifiers affect the previous item in the result list.
|
159
160
|
count, ch = get_quantifier(ch, pattern_iter)
|
plain/utils/termcolors.py
CHANGED
@@ -3,8 +3,8 @@ termcolors.py
|
|
3
3
|
"""
|
4
4
|
|
5
5
|
color_names = ("black", "red", "green", "yellow", "blue", "magenta", "cyan", "white")
|
6
|
-
foreground = {color_names[x]: "3
|
7
|
-
background = {color_names[x]: "4
|
6
|
+
foreground = {color_names[x]: f"3{x}" for x in range(8)}
|
7
|
+
background = {color_names[x]: f"4{x}" for x in range(8)}
|
8
8
|
|
9
9
|
RESET = "0"
|
10
10
|
opt_dict = {
|
@@ -47,7 +47,7 @@ def colorize(text="", opts=(), **kwargs):
|
|
47
47
|
"""
|
48
48
|
code_list = []
|
49
49
|
if text == "" and len(opts) == 1 and opts[0] == "reset":
|
50
|
-
return "\x1b[
|
50
|
+
return f"\x1b[{RESET}m"
|
51
51
|
for k, v in kwargs.items():
|
52
52
|
if k == "fg":
|
53
53
|
code_list.append(foreground[v])
|
@@ -58,7 +58,7 @@ def colorize(text="", opts=(), **kwargs):
|
|
58
58
|
code_list.append(opt_dict[o])
|
59
59
|
if "noreset" not in opts:
|
60
60
|
text = "{}\x1b[{}m".format(text or "", RESET)
|
61
|
-
return "{}{}".format(("\x1b[
|
61
|
+
return "{}{}".format(("\x1b[{}m".format(";".join(code_list))), text or "")
|
62
62
|
|
63
63
|
|
64
64
|
def make_style(opts=(), **kwargs):
|
plain/utils/text.py
CHANGED
@@ -53,7 +53,7 @@ def wrap(text, width):
|
|
53
53
|
yield line
|
54
54
|
line = ""
|
55
55
|
break
|
56
|
-
yield "
|
56
|
+
yield f"{line[: space - 1]}\n"
|
57
57
|
line = line[space:]
|
58
58
|
max_width = min((line.endswith("\n") and width + 1 or width), width)
|
59
59
|
if line:
|
@@ -224,7 +224,7 @@ class Truncator(SimpleLazyObject):
|
|
224
224
|
out += truncate_text
|
225
225
|
# Close any tags still open
|
226
226
|
for tag in open_tags:
|
227
|
-
out += "
|
227
|
+
out += f"</{tag}>"
|
228
228
|
# Return string
|
229
229
|
return out
|
230
230
|
|
@@ -242,7 +242,7 @@ def get_valid_filename(name):
|
|
242
242
|
s = str(name).strip().replace(" ", "_")
|
243
243
|
s = re.sub(r"(?u)[^-\w.]", "", s)
|
244
244
|
if s in {"", ".", ".."}:
|
245
|
-
raise SuspiciousFileOperation("Could not derive file name from '
|
245
|
+
raise SuspiciousFileOperation(f"Could not derive file name from '{name}'")
|
246
246
|
return s
|
247
247
|
|
248
248
|
|
@@ -407,9 +407,9 @@ def unescape_string_literal(s):
|
|
407
407
|
"'ab' c"
|
408
408
|
"""
|
409
409
|
if not s or s[0] not in "\"'" or s[-1] != s[0]:
|
410
|
-
raise ValueError("Not a string literal:
|
410
|
+
raise ValueError(f"Not a string literal: {s!r}")
|
411
411
|
quote = s[0]
|
412
|
-
return s[1:-1].replace(
|
412
|
+
return s[1:-1].replace(rf"\{quote}", quote).replace(r"\\", "\\")
|
413
413
|
|
414
414
|
|
415
415
|
@keep_lazy_text
|
@@ -475,9 +475,9 @@ def pluralize_lazy(singular, plural, number):
|
|
475
475
|
return values[number]
|
476
476
|
except KeyError:
|
477
477
|
raise KeyError(
|
478
|
-
"Your dictionary lacks key '
|
478
|
+
f"Your dictionary lacks key '{number}'. Please provide "
|
479
479
|
"it, because it is required to determine whether "
|
480
|
-
"string is singular or plural."
|
480
|
+
"string is singular or plural."
|
481
481
|
)
|
482
482
|
|
483
483
|
def _translate(self, number_value):
|
plain/utils/timesince.py
CHANGED
@@ -63,7 +63,7 @@ def timesince(d, now=None, reversed=False, time_strings=None, depth=2):
|
|
63
63
|
if now and not isinstance(now, datetime.datetime):
|
64
64
|
now = datetime.datetime(now.year, now.month, now.day)
|
65
65
|
|
66
|
-
now = now or datetime.datetime.now(datetime.
|
66
|
+
now = now or datetime.datetime.now(datetime.UTC if is_aware(d) else None)
|
67
67
|
|
68
68
|
if reversed:
|
69
69
|
d, now = now, d
|
plain/utils/timezone.py
CHANGED
@@ -5,7 +5,7 @@ Timezone-related classes and functions.
|
|
5
5
|
import functools
|
6
6
|
import zoneinfo
|
7
7
|
from contextlib import ContextDecorator
|
8
|
-
from datetime import datetime, timedelta, timezone, tzinfo
|
8
|
+
from datetime import UTC, datetime, timedelta, timezone, tzinfo
|
9
9
|
from threading import local
|
10
10
|
|
11
11
|
from plain.runtime import settings
|
@@ -33,7 +33,7 @@ def get_fixed_timezone(offset):
|
|
33
33
|
if isinstance(offset, timedelta):
|
34
34
|
offset = offset.total_seconds() // 60
|
35
35
|
sign = "-" if offset < 0 else "+"
|
36
|
-
hhmm = "%02d%02d" % divmod(abs(offset), 60)
|
36
|
+
hhmm = "%02d%02d" % divmod(abs(offset), 60) # noqa: UP031
|
37
37
|
name = sign + hhmm
|
38
38
|
return timezone(timedelta(minutes=offset), name)
|
39
39
|
|
@@ -95,7 +95,7 @@ def activate(timezone):
|
|
95
95
|
elif isinstance(timezone, str):
|
96
96
|
_active.value = zoneinfo.ZoneInfo(timezone)
|
97
97
|
else:
|
98
|
-
raise ValueError("Invalid timezone:
|
98
|
+
raise ValueError(f"Invalid timezone: {timezone!r}")
|
99
99
|
|
100
100
|
|
101
101
|
def deactivate():
|
@@ -165,7 +165,7 @@ def now():
|
|
165
165
|
"""
|
166
166
|
Return a timezone aware datetime.
|
167
167
|
"""
|
168
|
-
return datetime.now(tz=
|
168
|
+
return datetime.now(tz=UTC)
|
169
169
|
|
170
170
|
|
171
171
|
# By design, these four functions don't perform any checks on their arguments.
|
@@ -204,7 +204,7 @@ def make_aware(value, timezone=None):
|
|
204
204
|
timezone = get_current_timezone()
|
205
205
|
# Check that we won't overwrite the timezone of an aware datetime.
|
206
206
|
if is_aware(value):
|
207
|
-
raise ValueError("make_aware expects a naive datetime, got
|
207
|
+
raise ValueError(f"make_aware expects a naive datetime, got {value}")
|
208
208
|
# This may be wrong around DST changes!
|
209
209
|
return value.replace(tzinfo=timezone)
|
210
210
|
|
plain/validators.py
CHANGED
@@ -314,9 +314,7 @@ def ip_address_validators(protocol, unpack_ipv4):
|
|
314
314
|
return ip_address_validator_map[protocol.lower()]
|
315
315
|
except KeyError:
|
316
316
|
raise ValueError(
|
317
|
-
"The protocol '{}' is unknown. Supported: {}"
|
318
|
-
protocol, list(ip_address_validator_map)
|
319
|
-
)
|
317
|
+
f"The protocol '{protocol}' is unknown. Supported: {list(ip_address_validator_map)}"
|
320
318
|
)
|
321
319
|
|
322
320
|
|
plain/views/forms.py
CHANGED
@@ -20,8 +20,8 @@ class FormView(TemplateView):
|
|
20
20
|
"""Return an instance of the form to be used in this view."""
|
21
21
|
if not self.form_class:
|
22
22
|
raise ImproperlyConfigured(
|
23
|
-
"No form class provided. Define {
|
24
|
-
"{
|
23
|
+
f"No form class provided. Define {self.__class__.__name__}.form_class or override "
|
24
|
+
f"{self.__class__.__name__}.get_form()."
|
25
25
|
)
|
26
26
|
return self.form_class(**self.get_form_kwargs())
|
27
27
|
|
@@ -1,16 +1,12 @@
|
|
1
|
-
Metadata-Version: 2.
|
1
|
+
Metadata-Version: 2.4
|
2
2
|
Name: plain
|
3
|
-
Version: 0.13.
|
3
|
+
Version: 0.13.2
|
4
4
|
Summary: A web framework for building products with Python.
|
5
|
-
Author: Dave Gaeddert
|
6
|
-
|
7
|
-
Requires-Python: >=3.11
|
8
|
-
|
9
|
-
|
10
|
-
Classifier: Programming Language :: Python :: 3.12
|
11
|
-
Classifier: Programming Language :: Python :: 3.13
|
12
|
-
Requires-Dist: click (>=8.0.0)
|
13
|
-
Requires-Dist: jinja2 (>=3.1.2,<4.0.0)
|
5
|
+
Author-email: Dave Gaeddert <dave.gaeddert@dropseed.dev>
|
6
|
+
License-File: LICENSE
|
7
|
+
Requires-Python: >=3.11
|
8
|
+
Requires-Dist: click>=8.0.0
|
9
|
+
Requires-Dist: jinja2>=3.1.2
|
14
10
|
Description-Content-Type: text/markdown
|
15
11
|
|
16
12
|
<!-- This file is compiled from plain/plain/README.md. Do not edit this file directly. -->
|
@@ -48,4 +44,3 @@ With the official Plain ecosystem packages you can:
|
|
48
44
|
- Build [staff tooling and admin dashboards](https://plainframework.com/docs/plain-staff/)
|
49
45
|
|
50
46
|
Learn more at [plainframework.com](https://plainframework.com).
|
51
|
-
|
@@ -1,5 +1,12 @@
|
|
1
1
|
plain/README.md,sha256=mFsLBpqiHvuznV98eewupvo1JoQeQG0q87wNlXit21A,1695
|
2
2
|
plain/__main__.py,sha256=BiYbF-txGNbeRqp_CHQ9EZ_bCbbKq2iw51Z8RRUgIBY,105
|
3
|
+
plain/debug.py,sha256=NxiWJHB4Gi5JfJ4cnxzl-PZ6IgpSnUxg7a_dTQNq_lQ,705
|
4
|
+
plain/exceptions.py,sha256=pPAO8cIzNoqa2YrxG0d31C4P2V9SZ2OprHcjY9-qhIU,6332
|
5
|
+
plain/json.py,sha256=McJdsbMT1sYwkGRG--f2NSZz0hVXPMix9x3nKaaak2o,1262
|
6
|
+
plain/paginator.py,sha256=zCHCmCG8FEet6C28w2rUko9yiGFnOGCQxRbM_ssa9XY,6037
|
7
|
+
plain/signing.py,sha256=sf7g1Mp-FzdjFAEoLxHyu2YvbUl5w4FOtTVDAfq6TO0,8733
|
8
|
+
plain/validators.py,sha256=2tZh2Bvp955gejltwVtFGwfqw5-9VAOhKqos3Me4paY,19923
|
9
|
+
plain/wsgi.py,sha256=R6k5FiAElvGDApEbMPTT0MPqSD7n2e2Az5chQqJZU0I,236
|
3
10
|
plain/assets/README.md,sha256=048BzyQ2-BcsRiv6NiuLHHijOw96RK-e6lJ_Eq7g2pc,2857
|
4
11
|
plain/assets/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
5
12
|
plain/assets/compile.py,sha256=lsnciN85YjHe6d8VIKJi1L8r7NGHNzMOe9L87wObM5I,3287
|
@@ -7,49 +14,46 @@ plain/assets/finders.py,sha256=WEKAnXTmpuQ7UKLZz7vHPrKFdDOkuZSP6_JTKmIxrKg,1268
|
|
7
14
|
plain/assets/fingerprints.py,sha256=1NKAnnXVlncY5iimXztr0NL3RIjBKsNlZRIe6nmItJc,931
|
8
15
|
plain/assets/urls.py,sha256=ZTIoM1Zq35JaXZ3wFhXhfGa7VoITDNlH9i5RS0R5xow,933
|
9
16
|
plain/assets/views.py,sha256=dhjIpMu0GDR_VGbXM90_6RnC84C2C4bFv1RxDVklGBk,9173
|
10
|
-
plain/cli/README.md,sha256=
|
17
|
+
plain/cli/README.md,sha256=TvWCnNwb1rNthPzJglCRMKacN5H_RLeEjYBMe62Uz4M,2461
|
11
18
|
plain/cli/__init__.py,sha256=9ByBOIdM8DebChjNz-RH2atdz4vWe8somlwNEsbhwh4,40
|
12
|
-
plain/cli/cli.py,sha256=
|
19
|
+
plain/cli/cli.py,sha256=Y6QLN114ABuDBEy4heBBXLyfhkYvMopmFCcDy_O6ZKk,14537
|
13
20
|
plain/cli/formatting.py,sha256=1hZH13y1qwHcU2K2_Na388nw9uvoeQH8LrWL-O9h8Yc,2207
|
14
21
|
plain/cli/packages.py,sha256=69VH1bIi1-5N5l2jlBcR5EP0pt-v16sPar9arO3gCSE,2052
|
15
22
|
plain/cli/print.py,sha256=XraUYrgODOJquIiEv78wSCYGRBplHXtXSS9QtFG5hqY,217
|
16
|
-
plain/cli/startup.py,sha256=
|
23
|
+
plain/cli/startup.py,sha256=3LIz9JrIZoF52Sa0j0SCypQwEaBDkhvuGaBdtiQLr5Q,680
|
17
24
|
plain/csrf/README.md,sha256=RXMWMtHmzf30gVVNOfj0kD4xlSqFIPgJh-n7dIciaEM,163
|
18
|
-
plain/csrf/middleware.py,sha256=
|
25
|
+
plain/csrf/middleware.py,sha256=pD9un9oLK6YNAEPW0rsVDsHyhyxmAA_IDE5hXs6mHiA,17776
|
19
26
|
plain/csrf/views.py,sha256=YDgT451X16iUdCxpQ6rcHIy7nD0u7DAvCQl5-Mx5i9Y,219
|
20
|
-
plain/debug.py,sha256=NxiWJHB4Gi5JfJ4cnxzl-PZ6IgpSnUxg7a_dTQNq_lQ,705
|
21
|
-
plain/exceptions.py,sha256=tDS6l0epe_L9IlxpEdT2k2hWgEoAu8YBNIumNCtJ-WY,6333
|
22
27
|
plain/forms/README.md,sha256=fglB9MmHiEgfGGdZmcRstNl6eYaFljrElu2mzapK52M,377
|
23
28
|
plain/forms/__init__.py,sha256=UxqPwB8CiYPCQdHmUc59jadqaXqDmXBH8y4bt9vTPms,226
|
24
29
|
plain/forms/boundfield.py,sha256=LhydhCVR0okrli0-QBMjGjAJ8-06gTCXVEaBZhBouQk,1741
|
25
30
|
plain/forms/exceptions.py,sha256=XCLDRl5snIEDu5-8mLB0NnU_tegcBfyIHMiJxqvbxnc,164
|
26
31
|
plain/forms/fields.py,sha256=86ZE9jac6Zyg5vKsYGgyOUOIQLKxO--UomGXwA65tk4,35103
|
27
|
-
plain/forms/forms.py,sha256
|
32
|
+
plain/forms/forms.py,sha256=CiONLo9VhE7E1-u-UejX4XWxxwu6MvR-lVPaVAY7VQM,10441
|
28
33
|
plain/http/README.md,sha256=00zLFQ-FPjYXu3A8QsLhCCXxaT0ImvI5I-8xd3dp8WA,7
|
29
34
|
plain/http/__init__.py,sha256=DIsDRbBsCGa4qZgq-fUuQS0kkxfbTU_3KpIM9VvH04w,1067
|
30
35
|
plain/http/cookie.py,sha256=11FnSG3Plo6T3jZDbPoCw7SKh9ExdBio3pTmIO03URg,597
|
31
|
-
plain/http/multipartparser.py,sha256=
|
32
|
-
plain/http/request.py,sha256=
|
33
|
-
plain/http/response.py,sha256=
|
36
|
+
plain/http/multipartparser.py,sha256=k6BhpilFENQQ1cuGix6aa-jGwbhBVms2A2O01-s3_4c,27304
|
37
|
+
plain/http/request.py,sha256=sqE83ZaB1P2i7iEUQ6d-K_6X4xhpdRdsPiTVraiDoNU,25984
|
38
|
+
plain/http/response.py,sha256=wWZhz4AC6imR6-MI9P5TjaZKWRrxjLhSba9vqP-Iflc,24110
|
34
39
|
plain/internal/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
35
40
|
plain/internal/files/README.md,sha256=kMux-NU5qiH0o1K8IajYQT8VjrYl_jLk9LkGG_kGuSc,45
|
36
41
|
plain/internal/files/__init__.py,sha256=VctFgox4Q1AWF3klPaoCC5GIw5KeLafYjY5JmN8mAVw,63
|
37
42
|
plain/internal/files/base.py,sha256=CSq_BPKWY2kUib7pnoIvzi40isEyrKdkx1yHb8nPtLc,4817
|
38
|
-
plain/internal/files/locks.py,sha256=
|
39
|
-
plain/internal/files/move.py,sha256=
|
43
|
+
plain/internal/files/locks.py,sha256=z03q7IZD4tPMK3s1HKF3w_uetkFj6w6FTheLUxZsfB0,3616
|
44
|
+
plain/internal/files/move.py,sha256=jfdD29QhamxZjXRgqmZS4dJoJ4sK6M7QK1Km-69jWeo,3238
|
40
45
|
plain/internal/files/temp.py,sha256=UJJnCI8dqPIC8XXHU3-jG2-0svbkrgGlBs4yhciLm4c,2506
|
41
46
|
plain/internal/files/uploadedfile.py,sha256=JRB7T3quQjg-1y3l1ASPxywtSQZhaeMc45uFPIxvl7c,4192
|
42
|
-
plain/internal/files/uploadhandler.py,sha256=
|
43
|
-
plain/internal/files/utils.py,sha256=
|
47
|
+
plain/internal/files/uploadhandler.py,sha256=eEnd5onstypjHYtg367PnVWwCaF1kAPlLPSV7goIf_E,7198
|
48
|
+
plain/internal/files/utils.py,sha256=xN4HTJXDRdcoNyrL1dFd528MBwodRlHZM8DGTD_oBIg,2646
|
44
49
|
plain/internal/handlers/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
45
|
-
plain/internal/handlers/base.py,sha256=
|
46
|
-
plain/internal/handlers/exception.py,sha256=
|
47
|
-
plain/internal/handlers/wsgi.py,sha256=
|
50
|
+
plain/internal/handlers/base.py,sha256=I6549DBZUb-anqox7arzL9wpypH4bUCxZkitO76hljI,4794
|
51
|
+
plain/internal/handlers/exception.py,sha256=DH9gh1FyqgetFpMaB8yLIVE6phBTVPKQLA1GIn9MOeI,4555
|
52
|
+
plain/internal/handlers/wsgi.py,sha256=EWoH9EeetfgiL0BtoAe2Aof0VWaBrxl74Y9EP4xx0wc,7553
|
48
53
|
plain/internal/middleware/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
49
54
|
plain/internal/middleware/headers.py,sha256=UnJWnlVVLD-10h7PB_QSYeREBzLo-TS3C-_ahmZ6w0I,636
|
50
55
|
plain/internal/middleware/https.py,sha256=XpuQK8HicYX1jNanQHqNgyQ9rqe4NLUOZO3ZzKdsP8k,1203
|
51
|
-
plain/internal/middleware/slash.py,sha256=
|
52
|
-
plain/json.py,sha256=McJdsbMT1sYwkGRG--f2NSZz0hVXPMix9x3nKaaak2o,1262
|
56
|
+
plain/internal/middleware/slash.py,sha256=1rZsSSzXAA-vBb-dc2RlZaKW9gTT8YM8fJzwYGL4swA,2575
|
53
57
|
plain/logs/README.md,sha256=H6uVXdInYlasq0Z1WnhWnPmNwYQoZ1MSLPDQ4ZE7u4A,492
|
54
58
|
plain/logs/__init__.py,sha256=rASvo4qFBDIHfkACmGLNGa6lRGbG9PbNjW6FmBt95ys,168
|
55
59
|
plain/logs/configure.py,sha256=6mV7d1IxkDYT3VBz61qhIj0Esuy5l5QdQfsHaGCfI6w,1063
|
@@ -57,26 +61,24 @@ plain/logs/loggers.py,sha256=iz9SYcwP9w5QAuwpULl48SFkVyJuuMoQ_fdLgdCHpNg,2121
|
|
57
61
|
plain/logs/utils.py,sha256=9UzdCCQXJinGDs71Ngw297mlWkhgZStSd67ya4NOW98,1257
|
58
62
|
plain/packages/README.md,sha256=Vq1Nw3mmEmZ2IriQavuVi4BjcQC2nb8k7YIbnm8QjIg,799
|
59
63
|
plain/packages/__init__.py,sha256=DnHN1wwHXiXib4Y9BV__x9WrbUaTovoTIxW-tVyScTU,106
|
60
|
-
plain/packages/config.py,sha256
|
61
|
-
plain/packages/registry.py,sha256=
|
62
|
-
plain/paginator.py,sha256=4v5SbYotJH9HoNdzf-1j-AEy4ZLbLPuysf-VME4-6e0,6055
|
64
|
+
plain/packages/config.py,sha256=-je13ViDkXMEQXCSi0G539dG5_HPoFBKaK7cBEd_NAY,11070
|
65
|
+
plain/packages/registry.py,sha256=C1yv-JlzMs4HE-AYam_EdiTKNQwE8IN4qgt22PKxHDE,17920
|
63
66
|
plain/preflight/README.md,sha256=fgcfVRD6rq7IO8AffQhk49c-6akxaE8MQidRp69InDQ,59
|
64
67
|
plain/preflight/__init__.py,sha256=H-TNRvaddPtOGmv4RXoc1fxDV1AOb7_K3u7ECF8mV58,607
|
65
68
|
plain/preflight/files.py,sha256=wbHCNgps7o1c1zQNBd8FDCaVaqX90UwuvLgEQ_DbUpY,510
|
66
|
-
plain/preflight/messages.py,sha256=
|
67
|
-
plain/preflight/registry.py,sha256=
|
69
|
+
plain/preflight/messages.py,sha256=HwatjA6MRFfzFAnSOa_uAw1Pvk_CLuNfW3IYi71_1Mk,2322
|
70
|
+
plain/preflight/registry.py,sha256=7s7f_iEwURzv-Ye515P5lJWcHltd5Ca2fsX1Wpbf1wQ,2306
|
68
71
|
plain/preflight/security.py,sha256=sNpv5AHobPcaO48cOUGRNe2EjusTducjY8vyShR8EhI,2645
|
69
|
-
plain/preflight/urls.py,sha256=
|
72
|
+
plain/preflight/urls.py,sha256=VjK_B6tg22ugPO5VLY9gBCkDPW0mhcRr-64iv_12zCw,3003
|
70
73
|
plain/runtime/README.md,sha256=Q8VVO7JRGuYrDxzuYL6ptoilhclbecxKzpRXKgbWGkU,2061
|
71
74
|
plain/runtime/__init__.py,sha256=DH8TwKTGJhjviOy4yh_d051v8YGaAWMlFBPhK8ZuC9g,1499
|
72
|
-
plain/runtime/global_settings.py,sha256
|
75
|
+
plain/runtime/global_settings.py,sha256=T871IxXVARnpvxLOGh2YT0PTmafxcH18TuPUNNTE8vo,5499
|
73
76
|
plain/runtime/user_settings.py,sha256=-1xXUggueuOF3YlgnLfeyG55CUvR3azOGWr2UkTOmfs,11259
|
74
77
|
plain/signals/README.md,sha256=cd3tKEgH-xc88CUWyDxl4-qv-HBXx8VT32BXVwA5azA,230
|
75
78
|
plain/signals/__init__.py,sha256=eAs0kLqptuP6I31dWXeAqRNji3svplpAV4Ez6ktjwXM,131
|
76
79
|
plain/signals/dispatch/__init__.py,sha256=FzEygqV9HsM6gopio7O2Oh_X230nA4d5Q9s0sUjMq0E,292
|
77
80
|
plain/signals/dispatch/dispatcher.py,sha256=VxSlqn9PCOTghPPJLOqZPs6FNQZfV2BJpMfFMSg6Dtc,11531
|
78
81
|
plain/signals/dispatch/license.txt,sha256=o9EhDhsC4Q5HbmD-IfNGVTEkXtNE33r5rIt3lleJ8gc,1727
|
79
|
-
plain/signing.py,sha256=V6A6PTDYWekuwtQRI1iFD8dud5OHPZTv4EkeoZEHoXo,8737
|
80
82
|
plain/templates/README.md,sha256=VfA2HmrklG5weE1md85q9g84cWnMBEiXAynKzM7S1Sk,464
|
81
83
|
plain/templates/__init__.py,sha256=bX76FakE9T7mfK3N0deN85HlwHNQpeigytSC9Z8LcOs,451
|
82
84
|
plain/templates/core.py,sha256=iw58EAmyyv8N5HDA-Sq4-fLgz_qx8v8WJfurgR116jw,625
|
@@ -88,59 +90,57 @@ plain/templates/jinja/filters.py,sha256=3KJKKbxcv9dLzUDWPcaa88k3NU2m1GG3iMIgFhzX
|
|
88
90
|
plain/templates/jinja/globals.py,sha256=qhvQuikkRkOTpHSW5FwdsvoViJNlRgHq3-O7ZyeajsE,669
|
89
91
|
plain/test/README.md,sha256=Zso3Ir7a8vQerzKB6egjROQWkpveLAbscn7VTROPAiU,37
|
90
92
|
plain/test/__init__.py,sha256=rXe88Y602NP8DBnReSyXb7dUzKoWweLuT43j-qwOUl4,138
|
91
|
-
plain/test/client.py,sha256=
|
93
|
+
plain/test/client.py,sha256=xKhpLoA9c0rvEUrfuiewS9_xnCKBrkcump1-pAReQWo,31380
|
92
94
|
plain/urls/README.md,sha256=pWnCvgYkWN7rG7hSyBOtX4ZUP3iO7FhqM6lvwwYll6c,33
|
93
95
|
plain/urls/__init__.py,sha256=3UzwIufXjIks2K_X_Vms2MV19IqvyPLrXUeHU3WP47c,753
|
94
|
-
plain/urls/base.py,sha256=
|
95
|
-
plain/urls/conf.py,sha256=
|
96
|
+
plain/urls/base.py,sha256=Q1TzI5WvqYkN1U81fDom1q-AID4dXbszEMF6wAeTAI0,3717
|
97
|
+
plain/urls/conf.py,sha256=3R2dCr4iryMPXgUZqESZvqrhTLa5I7PzNY98SuCYYec,3491
|
96
98
|
plain/urls/converters.py,sha256=s2JZVOdzZC16lgobsI93hygcdH5L0Kj4742WEkXsVcs,1193
|
97
99
|
plain/urls/exceptions.py,sha256=q4iPh3Aa-zHbA-tw8v6WyX1J1n5WdAady2xvxFuyXB0,114
|
98
|
-
plain/urls/resolvers.py,sha256=
|
100
|
+
plain/urls/resolvers.py,sha256=Fb2F1cdTxKDn0ZvNX81zHBglZs_aKMgnFuSIJVxNiUk,27508
|
99
101
|
plain/utils/README.md,sha256=Bf5OG-MkOJDz_U8RGVreDfAI4M4nnPaLtk-LdinxHSc,99
|
100
102
|
plain/utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
101
103
|
plain/utils/_os.py,sha256=oqfiKZRbmHwwWSZP36SIajQnFDbImbB6gcyK0idAGl4,1988
|
102
|
-
plain/utils/cache.py,sha256=
|
104
|
+
plain/utils/cache.py,sha256=SM0jXxWU3XbaMPkthCsYWDYdZH5eOgGzKUgxV1ISNyE,11476
|
103
105
|
plain/utils/connection.py,sha256=NN7xRhy6qIWuOOhi1x9YdGcFcYhKepTiMUETeEMS0vY,2501
|
104
|
-
plain/utils/crypto.py,sha256=
|
105
|
-
plain/utils/datastructures.py,sha256=
|
106
|
-
plain/utils/dateformat.py,sha256=
|
107
|
-
plain/utils/dateparse.py,sha256=
|
106
|
+
plain/utils/crypto.py,sha256=zFDydnaqNMGYFHUc-CAn8f93685a17BhGusAcITH1lI,2662
|
107
|
+
plain/utils/datastructures.py,sha256=g4UYTbxIb_n8F9JWMP4dHPwUz71591fHreGATPO4qEc,10240
|
108
|
+
plain/utils/dateformat.py,sha256=nsy71l16QuPN0ozGpVlCU5Et101fhk9L38F-wqT5p5I,10203
|
109
|
+
plain/utils/dateparse.py,sha256=u9_tF85YteXSjW9KQzNg_pcCEFDZS3EGorCddcWU0vE,5351
|
108
110
|
plain/utils/dates.py,sha256=hSDKz8eIb3W5QjmGiklFZZELB0inYXsfiRUy49Cx-2Q,1226
|
109
111
|
plain/utils/deconstruct.py,sha256=7NwEFIDCiadAArUBFmiErzDgfIgDWeKqqQFDXwSgQoQ,1830
|
110
|
-
plain/utils/decorators.py,sha256=
|
112
|
+
plain/utils/decorators.py,sha256=6pcFQ5TezYZoO5Ys1KnImOsv0nUMsFCdxal-S6brUOc,3468
|
111
113
|
plain/utils/deprecation.py,sha256=qtj33kHEmJU7mGSrNcKidZsMo5W8MN-zrXzUq3aVVy8,131
|
112
114
|
plain/utils/duration.py,sha256=l0Gc41-DeyyAmpdy2XG-YO5UKxMf1NDpWIlQuD5hAn0,1162
|
113
115
|
plain/utils/email.py,sha256=puRTBVuz44YvpnqV3LT4nNIKqdqfY3L8zbDJIkqHk2Y,328
|
114
116
|
plain/utils/encoding.py,sha256=z8c7HxYW6wQiE4csx5Ui3WvzgbDzLGXY2aCP04_GZd4,7900
|
115
117
|
plain/utils/functional.py,sha256=7Z1LuPpS1y0ignX7QDzPq6zJqDZdCf_rFYLRR1rTSG0,14806
|
116
118
|
plain/utils/hashable.py,sha256=uLWobCCh7VcEPJ7xzVGPgigNVuTazYJbyzRzHTCI_wo,739
|
117
|
-
plain/utils/html.py,sha256=
|
118
|
-
plain/utils/http.py,sha256=
|
119
|
+
plain/utils/html.py,sha256=K8nJSiNRU54htQOfhezZAYspXaDGN3LjOE3SxmnQml8,13513
|
120
|
+
plain/utils/http.py,sha256=OmnqW_nYUaFN-pAEwjTEh9AkpfjKGmE51Ge6inNGB10,12710
|
119
121
|
plain/utils/inspect.py,sha256=lhDEOtmSLEub5Jj__MIgW3AyWOEVkaA6doJKKwBhZ6A,2235
|
120
|
-
plain/utils/ipv6.py,sha256=
|
122
|
+
plain/utils/ipv6.py,sha256=pISQ2AIlG8xXlxpphn388q03fq-fOrlu4GZR0YYjQXw,1267
|
121
123
|
plain/utils/itercompat.py,sha256=lacIDjczhxbwG4ON_KfG1H6VNPOGOpbRhnVhbedo2CY,184
|
122
|
-
plain/utils/module_loading.py,sha256=
|
123
|
-
plain/utils/regex_helper.py,sha256=
|
124
|
+
plain/utils/module_loading.py,sha256=CWl7Shoax9Zkevf1pM9PpS_0V69J5Cukjyj078UPCAw,2252
|
125
|
+
plain/utils/regex_helper.py,sha256=pAdh_xG52BOyXLsiuIMPFgduUAoWOEje1ZpjhcefxiA,12769
|
124
126
|
plain/utils/safestring.py,sha256=SHGhpbX6FFDKSYOY9zYAgAQX0g0exzRba7dM2bJalWs,1873
|
125
|
-
plain/utils/termcolors.py,sha256=
|
126
|
-
plain/utils/text.py,sha256=
|
127
|
-
plain/utils/timesince.py,sha256=
|
128
|
-
plain/utils/timezone.py,sha256=
|
127
|
+
plain/utils/termcolors.py,sha256=7ddeKVzePDMvKqauYlfhPDsXijZlCLONfxSHFE2o9jU,7394
|
128
|
+
plain/utils/text.py,sha256=qX7vECGH4Xk96qZRH9A1IyZA-mrJ-j62j3kDcLTdWK0,16586
|
129
|
+
plain/utils/timesince.py,sha256=d-9w_fqKS24IrHsh9-UX6SPNwrQvDp6QhZ_aJzM6AKY,4749
|
130
|
+
plain/utils/timezone.py,sha256=6u0sE-9RVp0_OCe0Y1KiYYQoq5THWLokZFQYY8jf78g,6221
|
129
131
|
plain/utils/tree.py,sha256=wdWzmfsgc26YDF2wxhAY3yVxXTixQYqYDKE9mL3L3ZY,4383
|
130
|
-
plain/validators.py,sha256=L9v9KtTe4iZhZVramZdKGf33R5Tt95FCdg2AJD2-2n0,19963
|
131
132
|
plain/views/README.md,sha256=qndsXKyNMnipPlLaAvgQeGxqXknNQwlFh31Yxk8rHp8,5994
|
132
133
|
plain/views/__init__.py,sha256=a-N1nkklVohJTtz0yD1MMaS0g66HviEjsKydNVVjvVc,392
|
133
134
|
plain/views/base.py,sha256=wMkCAbr3XqXyP8dJr-O9atA1-N6K4-cTFflLhSYGOpY,3227
|
134
135
|
plain/views/csrf.py,sha256=gO9npd_Ut_LoYF_u7Qb_ZsPRfSeE3aTPG97XlMp4oEo,724
|
135
136
|
plain/views/errors.py,sha256=Y4oGX4Z6D2COKcDEfINvXE1acE8Ad15KwNNWPs5BCfc,967
|
136
137
|
plain/views/exceptions.py,sha256=b4euI49ZUKS9O8AGAcFfiDpstzkRAuuj_uYQXzWNHME,138
|
137
|
-
plain/views/forms.py,sha256=
|
138
|
+
plain/views/forms.py,sha256=qnAj8yZNVM8cfOdRKkY6UakDzwA5W-VYgyd4jmKSKwk,2669
|
138
139
|
plain/views/objects.py,sha256=9QBYyb8PgkRirXCQ8-Pms4_yMzP37dfeL30hWRYmtZg,7909
|
139
140
|
plain/views/redirect.py,sha256=KLnlktzK6ZNMTlaEiZpMKQMEP5zeTgGLJ9BIkIJfwBo,1733
|
140
141
|
plain/views/templates.py,sha256=nF9CcdhhjAyp3LB0RrSYnBaHpHzMfPSw719RCdcXk7o,2007
|
141
|
-
plain/
|
142
|
-
plain-0.13.
|
143
|
-
plain-0.13.
|
144
|
-
plain-0.13.
|
145
|
-
plain-0.13.
|
146
|
-
plain-0.13.0.dist-info/RECORD,,
|
142
|
+
plain-0.13.2.dist-info/METADATA,sha256=OKgwkbINMVjNELMp-qHYsDi9HuGLu5lLXu_fMLszDFk,2518
|
143
|
+
plain-0.13.2.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
144
|
+
plain-0.13.2.dist-info/entry_points.txt,sha256=DHHprvufgd7xypiBiqMANYRnpJ9xPPYhYbnPGwOkWqE,40
|
145
|
+
plain-0.13.2.dist-info/licenses/LICENSE,sha256=m0D5O7QoH9l5Vz_rrX_9r-C8d9UNr_ciK6Qwac7o6yo,3175
|
146
|
+
plain-0.13.2.dist-info/RECORD,,
|
File without changes
|