plain 0.13.2__py3-none-any.whl → 0.14.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/cli/cli.py +4 -8
- plain/cli/packages.py +7 -3
- plain/http/response.py +5 -0
- plain/runtime/__init__.py +1 -1
- plain/runtime/user_settings.py +6 -6
- plain/test/client.py +8 -8
- plain/views/forms.py +2 -2
- plain/views/objects.py +2 -2
- {plain-0.13.2.dist-info → plain-0.14.1.dist-info}/METADATA +1 -1
- {plain-0.13.2.dist-info → plain-0.14.1.dist-info}/RECORD +13 -14
- plain/utils/termcolors.py +0 -221
- {plain-0.13.2.dist-info → plain-0.14.1.dist-info}/WHEEL +0 -0
- {plain-0.13.2.dist-info → plain-0.14.1.dist-info}/entry_points.txt +0 -0
- {plain-0.13.2.dist-info → plain-0.14.1.dist-info}/licenses/LICENSE +0 -0
plain/cli/cli.py
CHANGED
@@ -422,21 +422,17 @@ class AppCLIGroup(click.Group):
|
|
422
422
|
MODULE_NAME = "app.cli"
|
423
423
|
|
424
424
|
def list_commands(self, ctx):
|
425
|
-
|
426
|
-
find_spec(self.MODULE_NAME)
|
425
|
+
if find_spec(self.MODULE_NAME):
|
427
426
|
return ["app"]
|
428
|
-
|
427
|
+
else:
|
429
428
|
return []
|
430
429
|
|
431
430
|
def get_command(self, ctx, name):
|
432
431
|
if name != "app":
|
433
432
|
return
|
434
433
|
|
435
|
-
|
436
|
-
|
437
|
-
return cli.cli
|
438
|
-
except ModuleNotFoundError:
|
439
|
-
return
|
434
|
+
cli = importlib.import_module(self.MODULE_NAME)
|
435
|
+
return cli.cli
|
440
436
|
|
441
437
|
|
442
438
|
class PlainCommandCollection(click.CommandCollection):
|
plain/cli/packages.py
CHANGED
@@ -36,11 +36,15 @@ class InstalledPackagesGroup(click.Group):
|
|
36
36
|
def get_command(self, ctx, name):
|
37
37
|
# Try it as plain.x and just x (we don't know ahead of time which it is, but prefer plain.x)
|
38
38
|
for n in [self.PLAIN_APPS_PREFIX + name, name]:
|
39
|
-
|
40
|
-
|
41
|
-
|
39
|
+
if not find_spec(n):
|
40
|
+
# plain.<name> doesn't exist at all
|
41
|
+
continue
|
42
|
+
|
43
|
+
if not find_spec(f"{n}.{self.MODULE_NAME}"):
|
42
44
|
continue
|
43
45
|
|
46
|
+
cli = importlib.import_module(f"{n}.{self.MODULE_NAME}")
|
47
|
+
|
44
48
|
# Get the app's cli.py group
|
45
49
|
try:
|
46
50
|
return cli.cli
|
plain/http/response.py
CHANGED
@@ -7,6 +7,7 @@ import re
|
|
7
7
|
import sys
|
8
8
|
import time
|
9
9
|
from email.header import Header
|
10
|
+
from functools import cached_property
|
10
11
|
from http.client import responses
|
11
12
|
from http.cookies import SimpleCookie
|
12
13
|
from urllib.parse import urlparse
|
@@ -423,6 +424,10 @@ class Response(ResponseBase):
|
|
423
424
|
# Create a list of properly encoded bytestrings to support write().
|
424
425
|
self._container = [content]
|
425
426
|
|
427
|
+
@cached_property
|
428
|
+
def text(self):
|
429
|
+
return self.content.decode(self.charset or "utf-8")
|
430
|
+
|
426
431
|
def __iter__(self):
|
427
432
|
return iter(self._container)
|
428
433
|
|
plain/runtime/__init__.py
CHANGED
@@ -43,7 +43,7 @@ def setup():
|
|
43
43
|
# Automatically put the project dir on the Python path
|
44
44
|
# which doesn't otherwise happen when you run `plain` commands.
|
45
45
|
# This makes "app.<module>" imports and relative imports work.
|
46
|
-
if APP_PATH.parent not in sys.path:
|
46
|
+
if APP_PATH.parent.as_posix() not in sys.path:
|
47
47
|
sys.path.insert(0, APP_PATH.parent.as_posix())
|
48
48
|
|
49
49
|
configure_logging(settings.LOGGING)
|
plain/runtime/user_settings.py
CHANGED
@@ -4,6 +4,7 @@ import os
|
|
4
4
|
import time
|
5
5
|
import types
|
6
6
|
import typing
|
7
|
+
from importlib.util import find_spec
|
7
8
|
from pathlib import Path
|
8
9
|
|
9
10
|
from plain.exceptions import ImproperlyConfigured
|
@@ -101,12 +102,11 @@ class Settings:
|
|
101
102
|
|
102
103
|
def _load_default_settings(self, settings_module):
|
103
104
|
for entry in getattr(settings_module, "INSTALLED_PACKAGES", []):
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
except ModuleNotFoundError:
|
105
|
+
if isinstance(entry, PackageConfig):
|
106
|
+
app_settings = entry.module.default_settings
|
107
|
+
elif find_spec(f"{entry}.default_settings"):
|
108
|
+
app_settings = importlib.import_module(f"{entry}.default_settings")
|
109
|
+
else:
|
110
110
|
continue
|
111
111
|
|
112
112
|
self._load_module_settings(app_settings)
|
plain/test/client.py
CHANGED
@@ -5,7 +5,6 @@ import sys
|
|
5
5
|
from functools import partial
|
6
6
|
from http import HTTPStatus
|
7
7
|
from http.cookies import SimpleCookie
|
8
|
-
from importlib import import_module
|
9
8
|
from io import BytesIO, IOBase
|
10
9
|
from itertools import chain
|
11
10
|
from urllib.parse import unquote_to_bytes, urljoin, urlparse, urlsplit
|
@@ -21,6 +20,7 @@ from plain.utils.encoding import force_bytes
|
|
21
20
|
from plain.utils.functional import SimpleLazyObject
|
22
21
|
from plain.utils.http import urlencode
|
23
22
|
from plain.utils.itercompat import is_iterable
|
23
|
+
from plain.utils.module_loading import import_string
|
24
24
|
from plain.utils.regex_helper import _lazy_re_compile
|
25
25
|
|
26
26
|
__all__ = (
|
@@ -562,11 +562,11 @@ class ClientMixin:
|
|
562
562
|
@property
|
563
563
|
def session(self):
|
564
564
|
"""Return the current session variables."""
|
565
|
-
|
565
|
+
Session = import_string(settings.SESSION_CLASS)
|
566
566
|
cookie = self.cookies.get(settings.SESSION_COOKIE_NAME)
|
567
567
|
if cookie:
|
568
|
-
return
|
569
|
-
session =
|
568
|
+
return Session(cookie.value)
|
569
|
+
session = Session()
|
570
570
|
session.save()
|
571
571
|
self.cookies[settings.SESSION_COOKIE_NAME] = session.session_key
|
572
572
|
return session
|
@@ -582,8 +582,8 @@ class ClientMixin:
|
|
582
582
|
if self.session:
|
583
583
|
request.session = self.session
|
584
584
|
else:
|
585
|
-
|
586
|
-
request.session =
|
585
|
+
Session = import_string(settings.SESSION_CLASS)
|
586
|
+
request.session = Session()
|
587
587
|
login(request, user)
|
588
588
|
# Save the session values.
|
589
589
|
request.session.save()
|
@@ -608,8 +608,8 @@ class ClientMixin:
|
|
608
608
|
request.session = self.session
|
609
609
|
request.user = get_user(request)
|
610
610
|
else:
|
611
|
-
|
612
|
-
request.session =
|
611
|
+
Session = import_string(settings.SESSION_CLASS)
|
612
|
+
request.session = Session()
|
613
613
|
logout(request)
|
614
614
|
self.cookies = SimpleCookie()
|
615
615
|
|
plain/views/forms.py
CHANGED
@@ -40,7 +40,7 @@ class FormView(TemplateView):
|
|
40
40
|
)
|
41
41
|
return kwargs
|
42
42
|
|
43
|
-
def get_success_url(self) -> str:
|
43
|
+
def get_success_url(self, form: "BaseForm") -> str:
|
44
44
|
"""Return the URL to redirect to after processing a valid form."""
|
45
45
|
if not self.success_url:
|
46
46
|
raise ImproperlyConfigured("No URL to redirect to. Provide a success_url.")
|
@@ -48,7 +48,7 @@ class FormView(TemplateView):
|
|
48
48
|
|
49
49
|
def form_valid(self, form: "BaseForm") -> Response:
|
50
50
|
"""If the form is valid, redirect to the supplied URL."""
|
51
|
-
return ResponseRedirect(self.get_success_url())
|
51
|
+
return ResponseRedirect(self.get_success_url(form))
|
52
52
|
|
53
53
|
def form_invalid(self, form: "BaseForm") -> Response:
|
54
54
|
"""If the form is invalid, render the invalid form."""
|
plain/views/objects.py
CHANGED
@@ -93,7 +93,7 @@ class CreateView(ObjectTemplateViewMixin, FormView):
|
|
93
93
|
self.object = None
|
94
94
|
|
95
95
|
# TODO? would rather you have to specify this...
|
96
|
-
def get_success_url(self):
|
96
|
+
def get_success_url(self, form):
|
97
97
|
"""Return the URL to redirect to after processing a valid form."""
|
98
98
|
if self.success_url:
|
99
99
|
url = self.success_url.format(**self.object.__dict__)
|
@@ -126,7 +126,7 @@ class UpdateView(ObjectTemplateViewMixin, FormView):
|
|
126
126
|
self.load_object()
|
127
127
|
return super().post()
|
128
128
|
|
129
|
-
def get_success_url(self):
|
129
|
+
def get_success_url(self, form):
|
130
130
|
"""Return the URL to redirect to after processing a valid form."""
|
131
131
|
if self.success_url:
|
132
132
|
url = self.success_url.format(**self.object.__dict__)
|
@@ -16,9 +16,9 @@ plain/assets/urls.py,sha256=ZTIoM1Zq35JaXZ3wFhXhfGa7VoITDNlH9i5RS0R5xow,933
|
|
16
16
|
plain/assets/views.py,sha256=dhjIpMu0GDR_VGbXM90_6RnC84C2C4bFv1RxDVklGBk,9173
|
17
17
|
plain/cli/README.md,sha256=TvWCnNwb1rNthPzJglCRMKacN5H_RLeEjYBMe62Uz4M,2461
|
18
18
|
plain/cli/__init__.py,sha256=9ByBOIdM8DebChjNz-RH2atdz4vWe8somlwNEsbhwh4,40
|
19
|
-
plain/cli/cli.py,sha256=
|
19
|
+
plain/cli/cli.py,sha256=akk7koDuFXNpFPsSv4mzJNbtEuXTSXTeMFhFGUbbB9A,14426
|
20
20
|
plain/cli/formatting.py,sha256=1hZH13y1qwHcU2K2_Na388nw9uvoeQH8LrWL-O9h8Yc,2207
|
21
|
-
plain/cli/packages.py,sha256=
|
21
|
+
plain/cli/packages.py,sha256=FqRJaizaxpQ8lSS4nYNjqIGpYGDbeTmCXCvkGxusGOM,2160
|
22
22
|
plain/cli/print.py,sha256=XraUYrgODOJquIiEv78wSCYGRBplHXtXSS9QtFG5hqY,217
|
23
23
|
plain/cli/startup.py,sha256=3LIz9JrIZoF52Sa0j0SCypQwEaBDkhvuGaBdtiQLr5Q,680
|
24
24
|
plain/csrf/README.md,sha256=RXMWMtHmzf30gVVNOfj0kD4xlSqFIPgJh-n7dIciaEM,163
|
@@ -35,7 +35,7 @@ plain/http/__init__.py,sha256=DIsDRbBsCGa4qZgq-fUuQS0kkxfbTU_3KpIM9VvH04w,1067
|
|
35
35
|
plain/http/cookie.py,sha256=11FnSG3Plo6T3jZDbPoCw7SKh9ExdBio3pTmIO03URg,597
|
36
36
|
plain/http/multipartparser.py,sha256=k6BhpilFENQQ1cuGix6aa-jGwbhBVms2A2O01-s3_4c,27304
|
37
37
|
plain/http/request.py,sha256=sqE83ZaB1P2i7iEUQ6d-K_6X4xhpdRdsPiTVraiDoNU,25984
|
38
|
-
plain/http/response.py,sha256=
|
38
|
+
plain/http/response.py,sha256=QtJM4m8_imbYXSkwOAtMu9WCRZktvTsa4ZmVUAvz6bI,24250
|
39
39
|
plain/internal/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
40
40
|
plain/internal/files/README.md,sha256=kMux-NU5qiH0o1K8IajYQT8VjrYl_jLk9LkGG_kGuSc,45
|
41
41
|
plain/internal/files/__init__.py,sha256=VctFgox4Q1AWF3klPaoCC5GIw5KeLafYjY5JmN8mAVw,63
|
@@ -71,9 +71,9 @@ plain/preflight/registry.py,sha256=7s7f_iEwURzv-Ye515P5lJWcHltd5Ca2fsX1Wpbf1wQ,2
|
|
71
71
|
plain/preflight/security.py,sha256=sNpv5AHobPcaO48cOUGRNe2EjusTducjY8vyShR8EhI,2645
|
72
72
|
plain/preflight/urls.py,sha256=VjK_B6tg22ugPO5VLY9gBCkDPW0mhcRr-64iv_12zCw,3003
|
73
73
|
plain/runtime/README.md,sha256=Q8VVO7JRGuYrDxzuYL6ptoilhclbecxKzpRXKgbWGkU,2061
|
74
|
-
plain/runtime/__init__.py,sha256=
|
74
|
+
plain/runtime/__init__.py,sha256=ZfypqlhtbWUoJ84vLW4aKgpx2HsdtdJfDZnbbZw6kLE,1510
|
75
75
|
plain/runtime/global_settings.py,sha256=T871IxXVARnpvxLOGh2YT0PTmafxcH18TuPUNNTE8vo,5499
|
76
|
-
plain/runtime/user_settings.py,sha256
|
76
|
+
plain/runtime/user_settings.py,sha256=r6uQ-h0QxX3gSB_toJJekEbSikXXdNSb8ykUtwGTpdY,11280
|
77
77
|
plain/signals/README.md,sha256=cd3tKEgH-xc88CUWyDxl4-qv-HBXx8VT32BXVwA5azA,230
|
78
78
|
plain/signals/__init__.py,sha256=eAs0kLqptuP6I31dWXeAqRNji3svplpAV4Ez6ktjwXM,131
|
79
79
|
plain/signals/dispatch/__init__.py,sha256=FzEygqV9HsM6gopio7O2Oh_X230nA4d5Q9s0sUjMq0E,292
|
@@ -90,7 +90,7 @@ plain/templates/jinja/filters.py,sha256=3KJKKbxcv9dLzUDWPcaa88k3NU2m1GG3iMIgFhzX
|
|
90
90
|
plain/templates/jinja/globals.py,sha256=qhvQuikkRkOTpHSW5FwdsvoViJNlRgHq3-O7ZyeajsE,669
|
91
91
|
plain/test/README.md,sha256=Zso3Ir7a8vQerzKB6egjROQWkpveLAbscn7VTROPAiU,37
|
92
92
|
plain/test/__init__.py,sha256=rXe88Y602NP8DBnReSyXb7dUzKoWweLuT43j-qwOUl4,138
|
93
|
-
plain/test/client.py,sha256=
|
93
|
+
plain/test/client.py,sha256=MYAvM1HOSfEktNEOSb9662qkhHfvnxYlY00Ckj3dL3I,31349
|
94
94
|
plain/urls/README.md,sha256=pWnCvgYkWN7rG7hSyBOtX4ZUP3iO7FhqM6lvwwYll6c,33
|
95
95
|
plain/urls/__init__.py,sha256=3UzwIufXjIks2K_X_Vms2MV19IqvyPLrXUeHU3WP47c,753
|
96
96
|
plain/urls/base.py,sha256=Q1TzI5WvqYkN1U81fDom1q-AID4dXbszEMF6wAeTAI0,3717
|
@@ -124,7 +124,6 @@ plain/utils/itercompat.py,sha256=lacIDjczhxbwG4ON_KfG1H6VNPOGOpbRhnVhbedo2CY,184
|
|
124
124
|
plain/utils/module_loading.py,sha256=CWl7Shoax9Zkevf1pM9PpS_0V69J5Cukjyj078UPCAw,2252
|
125
125
|
plain/utils/regex_helper.py,sha256=pAdh_xG52BOyXLsiuIMPFgduUAoWOEje1ZpjhcefxiA,12769
|
126
126
|
plain/utils/safestring.py,sha256=SHGhpbX6FFDKSYOY9zYAgAQX0g0exzRba7dM2bJalWs,1873
|
127
|
-
plain/utils/termcolors.py,sha256=7ddeKVzePDMvKqauYlfhPDsXijZlCLONfxSHFE2o9jU,7394
|
128
127
|
plain/utils/text.py,sha256=qX7vECGH4Xk96qZRH9A1IyZA-mrJ-j62j3kDcLTdWK0,16586
|
129
128
|
plain/utils/timesince.py,sha256=d-9w_fqKS24IrHsh9-UX6SPNwrQvDp6QhZ_aJzM6AKY,4749
|
130
129
|
plain/utils/timezone.py,sha256=6u0sE-9RVp0_OCe0Y1KiYYQoq5THWLokZFQYY8jf78g,6221
|
@@ -135,12 +134,12 @@ plain/views/base.py,sha256=wMkCAbr3XqXyP8dJr-O9atA1-N6K4-cTFflLhSYGOpY,3227
|
|
135
134
|
plain/views/csrf.py,sha256=gO9npd_Ut_LoYF_u7Qb_ZsPRfSeE3aTPG97XlMp4oEo,724
|
136
135
|
plain/views/errors.py,sha256=Y4oGX4Z6D2COKcDEfINvXE1acE8Ad15KwNNWPs5BCfc,967
|
137
136
|
plain/views/exceptions.py,sha256=b4euI49ZUKS9O8AGAcFfiDpstzkRAuuj_uYQXzWNHME,138
|
138
|
-
plain/views/forms.py,sha256=
|
139
|
-
plain/views/objects.py,sha256=
|
137
|
+
plain/views/forms.py,sha256=RhlaUcZCkeqokY_fvv-NOS-kgZAG4XhDLOPbf9K_Zlc,2691
|
138
|
+
plain/views/objects.py,sha256=fRfS6KNehIGqkbPw4nSafj8HStxYExHmbggolBbzcxs,7921
|
140
139
|
plain/views/redirect.py,sha256=KLnlktzK6ZNMTlaEiZpMKQMEP5zeTgGLJ9BIkIJfwBo,1733
|
141
140
|
plain/views/templates.py,sha256=nF9CcdhhjAyp3LB0RrSYnBaHpHzMfPSw719RCdcXk7o,2007
|
142
|
-
plain-0.
|
143
|
-
plain-0.
|
144
|
-
plain-0.
|
145
|
-
plain-0.
|
146
|
-
plain-0.
|
141
|
+
plain-0.14.1.dist-info/METADATA,sha256=TcNf9s_L6irqxS7NOX_4RRSASEuzIBW9kshjZ_DaUg8,2518
|
142
|
+
plain-0.14.1.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
143
|
+
plain-0.14.1.dist-info/entry_points.txt,sha256=DHHprvufgd7xypiBiqMANYRnpJ9xPPYhYbnPGwOkWqE,40
|
144
|
+
plain-0.14.1.dist-info/licenses/LICENSE,sha256=m0D5O7QoH9l5Vz_rrX_9r-C8d9UNr_ciK6Qwac7o6yo,3175
|
145
|
+
plain-0.14.1.dist-info/RECORD,,
|
plain/utils/termcolors.py
DELETED
@@ -1,221 +0,0 @@
|
|
1
|
-
"""
|
2
|
-
termcolors.py
|
3
|
-
"""
|
4
|
-
|
5
|
-
color_names = ("black", "red", "green", "yellow", "blue", "magenta", "cyan", "white")
|
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
|
-
|
9
|
-
RESET = "0"
|
10
|
-
opt_dict = {
|
11
|
-
"bold": "1",
|
12
|
-
"underscore": "4",
|
13
|
-
"blink": "5",
|
14
|
-
"reverse": "7",
|
15
|
-
"conceal": "8",
|
16
|
-
}
|
17
|
-
|
18
|
-
|
19
|
-
def colorize(text="", opts=(), **kwargs):
|
20
|
-
"""
|
21
|
-
Return your text, enclosed in ANSI graphics codes.
|
22
|
-
|
23
|
-
Depends on the keyword arguments 'fg' and 'bg', and the contents of
|
24
|
-
the opts tuple/list.
|
25
|
-
|
26
|
-
Return the RESET code if no parameters are given.
|
27
|
-
|
28
|
-
Valid colors:
|
29
|
-
'black', 'red', 'green', 'yellow', 'blue', 'magenta', 'cyan', 'white'
|
30
|
-
|
31
|
-
Valid options:
|
32
|
-
'bold'
|
33
|
-
'underscore'
|
34
|
-
'blink'
|
35
|
-
'reverse'
|
36
|
-
'conceal'
|
37
|
-
'noreset' - string will not be auto-terminated with the RESET code
|
38
|
-
|
39
|
-
Examples:
|
40
|
-
colorize('hello', fg='red', bg='blue', opts=('blink',))
|
41
|
-
colorize()
|
42
|
-
colorize('goodbye', opts=('underscore',))
|
43
|
-
print(colorize('first line', fg='red', opts=('noreset',)))
|
44
|
-
print('this should be red too')
|
45
|
-
print(colorize('and so should this'))
|
46
|
-
print('this should not be red')
|
47
|
-
"""
|
48
|
-
code_list = []
|
49
|
-
if text == "" and len(opts) == 1 and opts[0] == "reset":
|
50
|
-
return f"\x1b[{RESET}m"
|
51
|
-
for k, v in kwargs.items():
|
52
|
-
if k == "fg":
|
53
|
-
code_list.append(foreground[v])
|
54
|
-
elif k == "bg":
|
55
|
-
code_list.append(background[v])
|
56
|
-
for o in opts:
|
57
|
-
if o in opt_dict:
|
58
|
-
code_list.append(opt_dict[o])
|
59
|
-
if "noreset" not in opts:
|
60
|
-
text = "{}\x1b[{}m".format(text or "", RESET)
|
61
|
-
return "{}{}".format(("\x1b[{}m".format(";".join(code_list))), text or "")
|
62
|
-
|
63
|
-
|
64
|
-
def make_style(opts=(), **kwargs):
|
65
|
-
"""
|
66
|
-
Return a function with default parameters for colorize()
|
67
|
-
|
68
|
-
Example:
|
69
|
-
bold_red = make_style(opts=('bold',), fg='red')
|
70
|
-
print(bold_red('hello'))
|
71
|
-
KEYWORD = make_style(fg='yellow')
|
72
|
-
COMMENT = make_style(fg='blue', opts=('bold',))
|
73
|
-
"""
|
74
|
-
return lambda text: colorize(text, opts, **kwargs)
|
75
|
-
|
76
|
-
|
77
|
-
NOCOLOR_PALETTE = "nocolor"
|
78
|
-
DARK_PALETTE = "dark"
|
79
|
-
LIGHT_PALETTE = "light"
|
80
|
-
|
81
|
-
PALETTES = {
|
82
|
-
NOCOLOR_PALETTE: {
|
83
|
-
"ERROR": {},
|
84
|
-
"SUCCESS": {},
|
85
|
-
"WARNING": {},
|
86
|
-
"NOTICE": {},
|
87
|
-
"SQL_FIELD": {},
|
88
|
-
"SQL_COLTYPE": {},
|
89
|
-
"SQL_KEYWORD": {},
|
90
|
-
"SQL_TABLE": {},
|
91
|
-
"HTTP_INFO": {},
|
92
|
-
"HTTP_SUCCESS": {},
|
93
|
-
"HTTP_REDIRECT": {},
|
94
|
-
"HTTP_NOT_MODIFIED": {},
|
95
|
-
"HTTP_BAD_REQUEST": {},
|
96
|
-
"HTTP_NOT_FOUND": {},
|
97
|
-
"HTTP_SERVER_ERROR": {},
|
98
|
-
"MIGRATE_HEADING": {},
|
99
|
-
"MIGRATE_LABEL": {},
|
100
|
-
},
|
101
|
-
DARK_PALETTE: {
|
102
|
-
"ERROR": {"fg": "red", "opts": ("bold",)},
|
103
|
-
"SUCCESS": {"fg": "green", "opts": ("bold",)},
|
104
|
-
"WARNING": {"fg": "yellow", "opts": ("bold",)},
|
105
|
-
"NOTICE": {"fg": "red"},
|
106
|
-
"SQL_FIELD": {"fg": "green", "opts": ("bold",)},
|
107
|
-
"SQL_COLTYPE": {"fg": "green"},
|
108
|
-
"SQL_KEYWORD": {"fg": "yellow"},
|
109
|
-
"SQL_TABLE": {"opts": ("bold",)},
|
110
|
-
"HTTP_INFO": {"opts": ("bold",)},
|
111
|
-
"HTTP_SUCCESS": {},
|
112
|
-
"HTTP_REDIRECT": {"fg": "green"},
|
113
|
-
"HTTP_NOT_MODIFIED": {"fg": "cyan"},
|
114
|
-
"HTTP_BAD_REQUEST": {"fg": "red", "opts": ("bold",)},
|
115
|
-
"HTTP_NOT_FOUND": {"fg": "yellow"},
|
116
|
-
"HTTP_SERVER_ERROR": {"fg": "magenta", "opts": ("bold",)},
|
117
|
-
"MIGRATE_HEADING": {"fg": "cyan", "opts": ("bold",)},
|
118
|
-
"MIGRATE_LABEL": {"opts": ("bold",)},
|
119
|
-
},
|
120
|
-
LIGHT_PALETTE: {
|
121
|
-
"ERROR": {"fg": "red", "opts": ("bold",)},
|
122
|
-
"SUCCESS": {"fg": "green", "opts": ("bold",)},
|
123
|
-
"WARNING": {"fg": "yellow", "opts": ("bold",)},
|
124
|
-
"NOTICE": {"fg": "red"},
|
125
|
-
"SQL_FIELD": {"fg": "green", "opts": ("bold",)},
|
126
|
-
"SQL_COLTYPE": {"fg": "green"},
|
127
|
-
"SQL_KEYWORD": {"fg": "blue"},
|
128
|
-
"SQL_TABLE": {"opts": ("bold",)},
|
129
|
-
"HTTP_INFO": {"opts": ("bold",)},
|
130
|
-
"HTTP_SUCCESS": {},
|
131
|
-
"HTTP_REDIRECT": {"fg": "green", "opts": ("bold",)},
|
132
|
-
"HTTP_NOT_MODIFIED": {"fg": "green"},
|
133
|
-
"HTTP_BAD_REQUEST": {"fg": "red", "opts": ("bold",)},
|
134
|
-
"HTTP_NOT_FOUND": {"fg": "red"},
|
135
|
-
"HTTP_SERVER_ERROR": {"fg": "magenta", "opts": ("bold",)},
|
136
|
-
"MIGRATE_HEADING": {"fg": "cyan", "opts": ("bold",)},
|
137
|
-
"MIGRATE_LABEL": {"opts": ("bold",)},
|
138
|
-
},
|
139
|
-
}
|
140
|
-
DEFAULT_PALETTE = DARK_PALETTE
|
141
|
-
|
142
|
-
|
143
|
-
def parse_color_setting(config_string):
|
144
|
-
"""Parse a DJANGO_COLORS environment variable to produce the system palette
|
145
|
-
|
146
|
-
The general form of a palette definition is:
|
147
|
-
|
148
|
-
"palette;role=fg;role=fg/bg;role=fg,option,option;role=fg/bg,option,option"
|
149
|
-
|
150
|
-
where:
|
151
|
-
palette is a named palette; one of 'light', 'dark', or 'nocolor'.
|
152
|
-
role is a named style used by Django
|
153
|
-
fg is a foreground color.
|
154
|
-
bg is a background color.
|
155
|
-
option is a display options.
|
156
|
-
|
157
|
-
Specifying a named palette is the same as manually specifying the individual
|
158
|
-
definitions for each role. Any individual definitions following the palette
|
159
|
-
definition will augment the base palette definition.
|
160
|
-
|
161
|
-
Valid roles:
|
162
|
-
'error', 'success', 'warning', 'notice', 'sql_field', 'sql_coltype',
|
163
|
-
'sql_keyword', 'sql_table', 'http_info', 'http_success',
|
164
|
-
'http_redirect', 'http_not_modified', 'http_bad_request',
|
165
|
-
'http_not_found', 'http_server_error', 'migrate_heading',
|
166
|
-
'migrate_label'
|
167
|
-
|
168
|
-
Valid colors:
|
169
|
-
'black', 'red', 'green', 'yellow', 'blue', 'magenta', 'cyan', 'white'
|
170
|
-
|
171
|
-
Valid options:
|
172
|
-
'bold', 'underscore', 'blink', 'reverse', 'conceal', 'noreset'
|
173
|
-
"""
|
174
|
-
if not config_string:
|
175
|
-
return PALETTES[DEFAULT_PALETTE]
|
176
|
-
|
177
|
-
# Split the color configuration into parts
|
178
|
-
parts = config_string.lower().split(";")
|
179
|
-
palette = PALETTES[NOCOLOR_PALETTE].copy()
|
180
|
-
for part in parts:
|
181
|
-
if part in PALETTES:
|
182
|
-
# A default palette has been specified
|
183
|
-
palette.update(PALETTES[part])
|
184
|
-
elif "=" in part:
|
185
|
-
# Process a palette defining string
|
186
|
-
definition = {}
|
187
|
-
|
188
|
-
# Break the definition into the role,
|
189
|
-
# plus the list of specific instructions.
|
190
|
-
# The role must be in upper case
|
191
|
-
role, instructions = part.split("=")
|
192
|
-
role = role.upper()
|
193
|
-
|
194
|
-
styles = instructions.split(",")
|
195
|
-
styles.reverse()
|
196
|
-
|
197
|
-
# The first instruction can contain a slash
|
198
|
-
# to break apart fg/bg.
|
199
|
-
colors = styles.pop().split("/")
|
200
|
-
colors.reverse()
|
201
|
-
fg = colors.pop()
|
202
|
-
if fg in color_names:
|
203
|
-
definition["fg"] = fg
|
204
|
-
if colors and colors[-1] in color_names:
|
205
|
-
definition["bg"] = colors[-1]
|
206
|
-
|
207
|
-
# All remaining instructions are options
|
208
|
-
opts = tuple(s for s in styles if s in opt_dict)
|
209
|
-
if opts:
|
210
|
-
definition["opts"] = opts
|
211
|
-
|
212
|
-
# The nocolor palette has all available roles.
|
213
|
-
# Use that palette as the basis for determining
|
214
|
-
# if the role is valid.
|
215
|
-
if role in PALETTES[NOCOLOR_PALETTE] and definition:
|
216
|
-
palette[role] = definition
|
217
|
-
|
218
|
-
# If there are no colors specified, return the empty palette.
|
219
|
-
if palette == PALETTES[NOCOLOR_PALETTE]:
|
220
|
-
return None
|
221
|
-
return palette
|
File without changes
|
File without changes
|
File without changes
|