plain.dev 0.4.0__py3-none-any.whl → 0.6.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/dev/cli.py +204 -19
- plain/dev/contribute/cli.py +10 -46
- plain/dev/precommit/cli.py +3 -7
- plain/dev/services.py +1 -5
- {plain_dev-0.4.0.dist-info → plain_dev-0.6.0.dist-info}/METADATA +1 -2
- {plain_dev-0.4.0.dist-info → plain_dev-0.6.0.dist-info}/RECORD +9 -9
- {plain_dev-0.4.0.dist-info → plain_dev-0.6.0.dist-info}/LICENSE +0 -0
- {plain_dev-0.4.0.dist-info → plain_dev-0.6.0.dist-info}/WHEEL +0 -0
- {plain_dev-0.4.0.dist-info → plain_dev-0.6.0.dist-info}/entry_points.txt +0 -0
plain/dev/cli.py
CHANGED
@@ -1,32 +1,31 @@
|
|
1
1
|
import json
|
2
2
|
import os
|
3
|
+
import platform
|
4
|
+
import shutil
|
3
5
|
import subprocess
|
4
6
|
import sys
|
7
|
+
import urllib.request
|
5
8
|
from importlib.util import find_spec
|
6
9
|
from pathlib import Path
|
7
10
|
|
8
11
|
import click
|
12
|
+
import tomllib
|
9
13
|
from honcho.manager import Manager as HonchoManager
|
10
14
|
|
11
|
-
from plain.runtime import APP_PATH
|
15
|
+
from plain.runtime import APP_PATH, settings
|
12
16
|
|
13
17
|
from .db import cli as db_cli
|
14
18
|
from .pid import Pid
|
15
19
|
from .services import Services
|
16
20
|
from .utils import has_pyproject_toml, plainpackage_installed
|
17
21
|
|
18
|
-
try:
|
19
|
-
import tomllib
|
20
|
-
except ModuleNotFoundError:
|
21
|
-
import tomli as tomllib
|
22
|
-
|
23
22
|
|
24
23
|
@click.group(invoke_without_command=True)
|
25
24
|
@click.pass_context
|
26
25
|
@click.option(
|
27
26
|
"--port",
|
28
27
|
"-p",
|
29
|
-
default=
|
28
|
+
default=8443,
|
30
29
|
type=int,
|
31
30
|
help="Port to run the web server on",
|
32
31
|
envvar="PORT",
|
@@ -61,31 +60,187 @@ class Dev:
|
|
61
60
|
"PORT": str(self.port),
|
62
61
|
"PYTHONPATH": os.path.join(APP_PATH.parent, "app"),
|
63
62
|
}
|
63
|
+
self.project_name = os.path.basename(os.getcwd())
|
64
|
+
self.domain = f"{self.project_name}.localhost"
|
65
|
+
|
66
|
+
# Paths for mkcert and certificates
|
67
|
+
self.mkcert_dir = Path.home() / ".plain" / "dev"
|
68
|
+
self.mkcert_bin = self.mkcert_dir / "mkcert"
|
69
|
+
self.certs_dir = (
|
70
|
+
Path(settings.PLAIN_TEMP_PATH) / "dev" / "certs"
|
71
|
+
) # Local project directory for certs
|
72
|
+
|
73
|
+
# Define certificate and key paths with clear filenames
|
74
|
+
self.cert_path = self.certs_dir / f"{self.domain}-cert.pem"
|
75
|
+
self.key_path = self.certs_dir / f"{self.domain}-key.pem"
|
64
76
|
|
65
77
|
def run(self):
|
66
78
|
pid = Pid()
|
67
79
|
pid.write()
|
68
80
|
|
69
81
|
try:
|
82
|
+
self.setup_mkcert()
|
83
|
+
self.generate_certs()
|
84
|
+
self.modify_hosts_file()
|
70
85
|
self.add_csrf_trusted_origins()
|
86
|
+
self.add_allowed_hosts()
|
71
87
|
self.run_preflight()
|
72
88
|
self.add_gunicorn()
|
73
89
|
self.add_tailwind()
|
74
90
|
self.add_pyproject_run()
|
75
91
|
self.add_services()
|
76
92
|
|
93
|
+
# Output the clickable link before starting the manager loop
|
94
|
+
url = f"https://{self.domain}:{self.port}/"
|
95
|
+
click.secho(
|
96
|
+
f"\nYour application is running at: {click.style(url, fg='green', underline=True)}\n",
|
97
|
+
bold=True,
|
98
|
+
)
|
99
|
+
|
77
100
|
self.manager.loop()
|
78
101
|
|
79
102
|
return self.manager.returncode
|
80
103
|
finally:
|
81
104
|
pid.rm()
|
82
105
|
|
83
|
-
def
|
84
|
-
|
106
|
+
def setup_mkcert(self):
|
107
|
+
"""Set up mkcert by checking if it's installed or downloading the binary and installing the local CA."""
|
108
|
+
if mkcert_path := shutil.which("mkcert"):
|
109
|
+
# mkcert is already installed somewhere
|
110
|
+
self.mkcert_bin = mkcert_path
|
111
|
+
else:
|
112
|
+
self.mkcert_dir.mkdir(parents=True, exist_ok=True)
|
113
|
+
if not self.mkcert_bin.exists():
|
114
|
+
system = platform.system()
|
115
|
+
arch = platform.machine()
|
116
|
+
|
117
|
+
# Map platform.machine() to mkcert's expected architecture strings
|
118
|
+
arch_map = {
|
119
|
+
"x86_64": "amd64",
|
120
|
+
"amd64": "amd64",
|
121
|
+
"AMD64": "amd64",
|
122
|
+
"arm64": "arm64",
|
123
|
+
"aarch64": "arm64",
|
124
|
+
}
|
125
|
+
arch = arch_map.get(
|
126
|
+
arch.lower(), "amd64"
|
127
|
+
) # Default to amd64 if unknown
|
128
|
+
|
129
|
+
if system == "Darwin":
|
130
|
+
os_name = "darwin"
|
131
|
+
elif system == "Linux":
|
132
|
+
os_name = "linux"
|
133
|
+
elif system == "Windows":
|
134
|
+
os_name = "windows"
|
135
|
+
else:
|
136
|
+
click.secho("Unsupported OS", fg="red")
|
137
|
+
sys.exit(1)
|
138
|
+
|
139
|
+
mkcert_url = f"https://dl.filippo.io/mkcert/latest?for={os_name}/{arch}"
|
140
|
+
click.secho(f"Downloading mkcert from {mkcert_url}...", bold=True)
|
141
|
+
urllib.request.urlretrieve(mkcert_url, self.mkcert_bin)
|
142
|
+
self.mkcert_bin.chmod(0o755)
|
143
|
+
self.mkcert_bin = str(self.mkcert_bin) # Convert Path object to string
|
144
|
+
|
145
|
+
if not self.is_mkcert_ca_installed():
|
146
|
+
click.secho(
|
147
|
+
"Installing mkcert local CA. You may be prompted for your password.",
|
148
|
+
bold=True,
|
149
|
+
)
|
150
|
+
subprocess.run([self.mkcert_bin, "-install"], check=True)
|
151
|
+
|
152
|
+
def is_mkcert_ca_installed(self):
|
153
|
+
"""Check if mkcert local CA is already installed using mkcert -check."""
|
154
|
+
try:
|
155
|
+
result = subprocess.run([self.mkcert_bin, "-check"], capture_output=True)
|
156
|
+
output = result.stdout.decode() + result.stderr.decode()
|
157
|
+
if "The local CA is not installed" in output:
|
158
|
+
return False
|
159
|
+
return True
|
160
|
+
except Exception as e:
|
161
|
+
click.secho(f"Error checking mkcert CA installation: {e}", fg="red")
|
162
|
+
return False
|
163
|
+
|
164
|
+
def generate_certs(self):
|
165
|
+
if self.cert_path.exists() and self.key_path.exists():
|
85
166
|
return
|
86
167
|
|
168
|
+
self.certs_dir.mkdir(parents=True, exist_ok=True)
|
169
|
+
|
170
|
+
# Generate SSL certificates using mkcert
|
171
|
+
click.secho(f"Generating SSL certificates for {self.domain}...", bold=True)
|
172
|
+
subprocess.run(
|
173
|
+
[
|
174
|
+
self.mkcert_bin,
|
175
|
+
"-cert-file",
|
176
|
+
str(self.cert_path),
|
177
|
+
"-key-file",
|
178
|
+
str(self.key_path),
|
179
|
+
self.domain,
|
180
|
+
],
|
181
|
+
check=True,
|
182
|
+
)
|
183
|
+
|
184
|
+
def modify_hosts_file(self):
|
185
|
+
"""Modify the hosts file to map the custom domain to 127.0.0.1."""
|
186
|
+
entry_identifier = "# Added by plain"
|
187
|
+
hosts_entry = f"127.0.0.1 {self.domain} {entry_identifier}"
|
188
|
+
|
189
|
+
if platform.system() == "Windows":
|
190
|
+
hosts_path = Path(r"C:\Windows\System32\drivers\etc\hosts")
|
191
|
+
try:
|
192
|
+
with hosts_path.open("r") as f:
|
193
|
+
content = f.read()
|
194
|
+
|
195
|
+
if hosts_entry in content:
|
196
|
+
return # Entry already exists; no action needed
|
197
|
+
|
198
|
+
# Entry does not exist; add it
|
199
|
+
with hosts_path.open("a") as f:
|
200
|
+
f.write(f"{hosts_entry}\n")
|
201
|
+
click.secho(f"Added {self.domain} to {hosts_path}", bold=True)
|
202
|
+
except PermissionError:
|
203
|
+
click.secho(
|
204
|
+
"Permission denied while modifying hosts file. Please run the script as an administrator.",
|
205
|
+
fg="red",
|
206
|
+
)
|
207
|
+
sys.exit(1)
|
208
|
+
else:
|
209
|
+
# For macOS and Linux
|
210
|
+
hosts_path = Path("/etc/hosts")
|
211
|
+
try:
|
212
|
+
with hosts_path.open("r") as f:
|
213
|
+
content = f.read()
|
214
|
+
|
215
|
+
if hosts_entry in content:
|
216
|
+
return # Entry already exists; no action needed
|
217
|
+
|
218
|
+
# Entry does not exist; append it using sudo
|
219
|
+
click.secho(
|
220
|
+
"Modifying /etc/hosts file. You may be prompted for your password.",
|
221
|
+
bold=True,
|
222
|
+
)
|
223
|
+
cmd = f"echo '{hosts_entry}' | sudo tee -a {hosts_path} >/dev/null"
|
224
|
+
subprocess.run(cmd, shell=True, check=True)
|
225
|
+
click.secho(f"Added {self.domain} to {hosts_path}", bold=True)
|
226
|
+
except PermissionError:
|
227
|
+
click.secho(
|
228
|
+
"Permission denied while accessing hosts file.",
|
229
|
+
fg="red",
|
230
|
+
)
|
231
|
+
sys.exit(1)
|
232
|
+
except subprocess.CalledProcessError:
|
233
|
+
click.secho(
|
234
|
+
"Failed to modify hosts file. Please ensure you have sudo privileges.",
|
235
|
+
fg="red",
|
236
|
+
)
|
237
|
+
sys.exit(1)
|
238
|
+
|
239
|
+
def add_csrf_trusted_origins(self):
|
87
240
|
csrf_trusted_origins = json.dumps(
|
88
|
-
[
|
241
|
+
[
|
242
|
+
f"https://{self.domain}:{self.port}",
|
243
|
+
]
|
89
244
|
)
|
90
245
|
|
91
246
|
click.secho(
|
@@ -93,10 +248,22 @@ class Dev:
|
|
93
248
|
bold=True,
|
94
249
|
)
|
95
250
|
|
96
|
-
# Set
|
251
|
+
# Set environment variables
|
97
252
|
self.plain_env["PLAIN_CSRF_TRUSTED_ORIGINS"] = csrf_trusted_origins
|
98
253
|
self.custom_process_env["PLAIN_CSRF_TRUSTED_ORIGINS"] = csrf_trusted_origins
|
99
254
|
|
255
|
+
def add_allowed_hosts(self):
|
256
|
+
allowed_hosts = json.dumps([self.domain])
|
257
|
+
|
258
|
+
click.secho(
|
259
|
+
f"Automatically set PLAIN_ALLOWED_HOSTS={click.style(allowed_hosts, underline=True)}",
|
260
|
+
bold=True,
|
261
|
+
)
|
262
|
+
|
263
|
+
# Set environment variables
|
264
|
+
self.plain_env["PLAIN_ALLOWED_HOSTS"] = allowed_hosts
|
265
|
+
self.custom_process_env["PLAIN_ALLOWED_HOSTS"] = allowed_hosts
|
266
|
+
|
100
267
|
def run_preflight(self):
|
101
268
|
if subprocess.run(["plain", "preflight"], env=self.plain_env).returncode:
|
102
269
|
click.secho("Preflight check failed!", fg="red")
|
@@ -105,16 +272,34 @@ class Dev:
|
|
105
272
|
def add_gunicorn(self):
|
106
273
|
plain_db_installed = find_spec("plain.models") is not None
|
107
274
|
|
108
|
-
#
|
109
|
-
# could return path from env.load?
|
275
|
+
# Watch .env files for reload
|
110
276
|
extra_watch_files = []
|
111
277
|
for f in os.listdir(APP_PATH.parent):
|
112
278
|
if f.startswith(".env"):
|
113
|
-
# Will include some extra, but good enough for now
|
114
279
|
extra_watch_files.append(f)
|
115
280
|
|
116
281
|
reload_extra = " ".join(f"--reload-extra-file {f}" for f in extra_watch_files)
|
117
|
-
|
282
|
+
gunicorn_cmd = [
|
283
|
+
"gunicorn",
|
284
|
+
"--bind",
|
285
|
+
f"{self.domain}:{self.port}",
|
286
|
+
"--certfile",
|
287
|
+
str(self.cert_path),
|
288
|
+
"--keyfile",
|
289
|
+
str(self.key_path),
|
290
|
+
"--reload",
|
291
|
+
"plain.wsgi:app",
|
292
|
+
"--timeout",
|
293
|
+
"60",
|
294
|
+
"--access-logfile",
|
295
|
+
"-",
|
296
|
+
"--error-logfile",
|
297
|
+
"-",
|
298
|
+
*reload_extra.split(),
|
299
|
+
"--access-logformat",
|
300
|
+
"'\"%(r)s\" status=%(s)s length=%(b)s dur=%(M)sms'",
|
301
|
+
]
|
302
|
+
gunicorn = " ".join(gunicorn_cmd)
|
118
303
|
|
119
304
|
if plain_db_installed:
|
120
305
|
runserver_cmd = f"plain models db-wait && plain migrate && {gunicorn}"
|
@@ -122,8 +307,7 @@ class Dev:
|
|
122
307
|
runserver_cmd = gunicorn
|
123
308
|
|
124
309
|
if "WEB_CONCURRENCY" not in self.plain_env:
|
125
|
-
# Default to two workers
|
126
|
-
# likely to get locked up
|
310
|
+
# Default to two workers to prevent lockups
|
127
311
|
self.plain_env["WEB_CONCURRENCY"] = "2"
|
128
312
|
|
129
313
|
self.manager.add_process("plain", runserver_cmd, env=self.plain_env)
|
@@ -141,9 +325,10 @@ class Dev:
|
|
141
325
|
with open(Path(APP_PATH.parent, "pyproject.toml"), "rb") as f:
|
142
326
|
pyproject = tomllib.load(f)
|
143
327
|
|
144
|
-
|
328
|
+
run_commands = (
|
145
329
|
pyproject.get("tool", {}).get("plain", {}).get("dev", {}).get("run", {})
|
146
|
-
)
|
330
|
+
)
|
331
|
+
for name, data in run_commands.items():
|
147
332
|
env = {
|
148
333
|
**self.custom_process_env,
|
149
334
|
**data.get("env", {}),
|
plain/dev/contribute/cli.py
CHANGED
@@ -3,7 +3,6 @@ import sys
|
|
3
3
|
from pathlib import Path
|
4
4
|
|
5
5
|
import click
|
6
|
-
import tomllib
|
7
6
|
|
8
7
|
|
9
8
|
@click.command("contribute")
|
@@ -13,22 +12,16 @@ def cli(package, repo):
|
|
13
12
|
"""Contribute to plain by linking a package locally."""
|
14
13
|
|
15
14
|
if package == "reset":
|
16
|
-
click.secho("Undoing any changes to pyproject.toml and
|
17
|
-
result = subprocess.run(["git", "checkout", "pyproject.toml", "
|
15
|
+
click.secho("Undoing any changes to pyproject.toml and uv.lock", bold=True)
|
16
|
+
result = subprocess.run(["git", "checkout", "pyproject.toml", "uv.lock"])
|
18
17
|
if result.returncode:
|
19
|
-
click.secho("Failed to checkout pyproject.toml and
|
18
|
+
click.secho("Failed to checkout pyproject.toml and uv.lock", fg="red")
|
20
19
|
sys.exit(result.returncode)
|
21
20
|
|
22
|
-
click.secho("
|
23
|
-
result = subprocess.run(["
|
21
|
+
click.secho("Running uv sync", bold=True)
|
22
|
+
result = subprocess.run(["uv", "sync"])
|
24
23
|
if result.returncode:
|
25
|
-
click.secho("Failed to
|
26
|
-
sys.exit(result.returncode)
|
27
|
-
|
28
|
-
click.secho("Running poetry install", bold=True)
|
29
|
-
result = subprocess.run(["poetry", "install"])
|
30
|
-
if result.returncode:
|
31
|
-
click.secho("Failed to install", fg="red")
|
24
|
+
click.secho("Failed to sync", fg="red")
|
32
25
|
sys.exit(result.returncode)
|
33
26
|
|
34
27
|
return
|
@@ -53,42 +46,14 @@ def cli(package, repo):
|
|
53
46
|
)
|
54
47
|
click.secho(f"Using repo at {repo} ({repo_branch} branch)", bold=True)
|
55
48
|
|
56
|
-
pyproject = Path("pyproject.toml")
|
57
|
-
if not pyproject.exists():
|
58
|
-
click.secho("pyproject.toml not found", fg="red")
|
59
|
-
return
|
60
|
-
|
61
|
-
poetry_group = "main"
|
62
|
-
|
63
|
-
with pyproject.open("rb") as f:
|
64
|
-
pyproject_data = tomllib.load(f)
|
65
|
-
poetry_dependencies = (
|
66
|
-
pyproject_data.get("tool", {}).get("poetry", {}).get("dependencies", {})
|
67
|
-
)
|
68
|
-
|
69
|
-
for group_name, group_data in (
|
70
|
-
pyproject_data.get("tool", {}).get("poetry", {}).get("group", {}).items()
|
71
|
-
):
|
72
|
-
if package in group_data.get("dependencies", {}).keys():
|
73
|
-
poetry_group = group_name
|
74
|
-
break
|
75
|
-
|
76
|
-
if not poetry_group and package not in poetry_dependencies.keys():
|
77
|
-
click.secho(
|
78
|
-
f"{package} not found in pyproject.toml (only poetry is supported)",
|
79
|
-
fg="red",
|
80
|
-
)
|
81
|
-
return
|
82
|
-
|
83
49
|
click.secho(f"Linking {package} to {repo}", bold=True)
|
84
50
|
if package == "plain" or package.startswith("plain-"):
|
85
51
|
result = subprocess.run(
|
86
52
|
[
|
87
|
-
"
|
53
|
+
"uv",
|
88
54
|
"add",
|
89
55
|
"--editable",
|
90
|
-
"--
|
91
|
-
poetry_group,
|
56
|
+
"--dev",
|
92
57
|
str(repo / package), # Link a subdirectory
|
93
58
|
]
|
94
59
|
)
|
@@ -98,11 +63,10 @@ def cli(package, repo):
|
|
98
63
|
elif package.startswith("plainx-"):
|
99
64
|
result = subprocess.run(
|
100
65
|
[
|
101
|
-
"
|
66
|
+
"uv",
|
102
67
|
"add",
|
103
68
|
"--editable",
|
104
|
-
"--
|
105
|
-
poetry_group,
|
69
|
+
"--dev",
|
106
70
|
str(repo),
|
107
71
|
]
|
108
72
|
)
|
plain/dev/precommit/cli.py
CHANGED
@@ -4,17 +4,13 @@ import sys
|
|
4
4
|
from importlib.util import find_spec
|
5
5
|
from pathlib import Path
|
6
6
|
|
7
|
+
import click
|
8
|
+
import tomllib
|
9
|
+
|
7
10
|
from plain.cli.print import print_event
|
8
11
|
|
9
12
|
from ..services import Services
|
10
13
|
|
11
|
-
try:
|
12
|
-
import tomllib
|
13
|
-
except ModuleNotFoundError:
|
14
|
-
import tomli as tomllib
|
15
|
-
|
16
|
-
import click
|
17
|
-
|
18
14
|
|
19
15
|
def install_git_hook():
|
20
16
|
hook_path = os.path.join(".git", "hooks", "pre-commit")
|
plain/dev/services.py
CHANGED
@@ -5,6 +5,7 @@ from importlib.util import find_spec
|
|
5
5
|
from pathlib import Path
|
6
6
|
|
7
7
|
import click
|
8
|
+
import tomllib
|
8
9
|
from honcho.manager import Manager as HonchoManager
|
9
10
|
|
10
11
|
from plain.runtime import APP_PATH
|
@@ -12,11 +13,6 @@ from plain.runtime import APP_PATH
|
|
12
13
|
from .pid import Pid
|
13
14
|
from .utils import has_pyproject_toml
|
14
15
|
|
15
|
-
try:
|
16
|
-
import tomllib
|
17
|
-
except ModuleNotFoundError:
|
18
|
-
import tomli as tomllib
|
19
|
-
|
20
16
|
|
21
17
|
class Services:
|
22
18
|
@staticmethod
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.1
|
2
2
|
Name: plain.dev
|
3
|
-
Version: 0.
|
3
|
+
Version: 0.6.0
|
4
4
|
Summary: Local development tools for Plain.
|
5
5
|
Home-page: https://plainframework.com
|
6
6
|
License: BSD-3-Clause
|
@@ -18,7 +18,6 @@ Requires-Dist: honcho (>=1.1.0,<2.0.0)
|
|
18
18
|
Requires-Dist: plain (<1.0.0)
|
19
19
|
Requires-Dist: psycopg[binary] (>=3.2.2,<4.0.0)
|
20
20
|
Requires-Dist: requests (>=2.0.0)
|
21
|
-
Requires-Dist: tomli (>=2.0.1,<3.0.0) ; python_version < "3.11"
|
22
21
|
Project-URL: Documentation, https://plainframework.com/docs/
|
23
22
|
Project-URL: Repository, https://github.com/dropseed/plain
|
24
23
|
Description-Content-Type: text/markdown
|
@@ -1,9 +1,9 @@
|
|
1
1
|
plain/dev/README.md,sha256=BQDaRKfsafIPzx7vtVt-zS-a8l6sxbQThhQTvu7tp3Y,3699
|
2
2
|
plain/dev/__init__.py,sha256=C1JrkNE5XX2DLgBXXLAV_UyhofwVd0ZPL59fPUMbOKo,139
|
3
|
-
plain/dev/cli.py,sha256=
|
3
|
+
plain/dev/cli.py,sha256=7MyA2-XExzFwYtv6q_TFEUXxelcPt2u3Ou51r9fGcDY,11740
|
4
4
|
plain/dev/config.py,sha256=h6o5YZtJhg-cFIWoqIDWuMCC5T09cxEsBaa3BP4Nii0,632
|
5
5
|
plain/dev/contribute/__init__.py,sha256=9ByBOIdM8DebChjNz-RH2atdz4vWe8somlwNEsbhwh4,40
|
6
|
-
plain/dev/contribute/cli.py,sha256=
|
6
|
+
plain/dev/contribute/cli.py,sha256=qZ7YmE_upbw-Y5NRpvaHnJTPp9kvn21fPQ7G0n1LAkg,2277
|
7
7
|
plain/dev/db/__init__.py,sha256=9ByBOIdM8DebChjNz-RH2atdz4vWe8somlwNEsbhwh4,40
|
8
8
|
plain/dev/db/cli.py,sha256=058HjRKLGz-FxauQEpwsPoh_LCiy-_NEIpRZl9W1ZKM,2855
|
9
9
|
plain/dev/db/container.py,sha256=RlPJU_CCMKA-zN8Kp0sYAu3jabOizxYAj8fSCsjCf60,5147
|
@@ -11,15 +11,15 @@ plain/dev/debug.py,sha256=fIrecLfAK_lXSDyn3WmYikzZSse3KY47xcVVbZqJGhk,294
|
|
11
11
|
plain/dev/default_settings.py,sha256=uXWYORWP_aRDwXIFXdu5kHyiBFUZzARIJdhPeFaX35c,75
|
12
12
|
plain/dev/pid.py,sha256=gRMBf7aGndrra1TnmKtPghTijnd0i0Xeo63mzfPWp7M,436
|
13
13
|
plain/dev/precommit/__init__.py,sha256=9ByBOIdM8DebChjNz-RH2atdz4vWe8somlwNEsbhwh4,40
|
14
|
-
plain/dev/precommit/cli.py,sha256=
|
14
|
+
plain/dev/precommit/cli.py,sha256=UNrQmWRKrkZ6WbzrrcnjZl8VHwNorOVTHGoRQsR4jp8,3422
|
15
15
|
plain/dev/requests.py,sha256=0HyCH7iZ32ne94ypMdE96z5iYb_Qbd705WItVik1SyA,6839
|
16
|
-
plain/dev/services.py,sha256=
|
16
|
+
plain/dev/services.py,sha256=Ypat8YFum0K_CLtkUuU2L6Y9Rg8GJBvJ0OqeVGMVT9g,2061
|
17
17
|
plain/dev/templates/dev/requests.html,sha256=kQKJZq5L77juuL_t8UjcAehEU61U4RXNnKaAET-wAm8,7627
|
18
18
|
plain/dev/urls.py,sha256=b4NL2I6Ok-t7nTPjRnKoz_LQRttE3_mp8l2NlmeYQ9I,146
|
19
19
|
plain/dev/utils.py,sha256=mL3C3l3GsKmtI6eF4sRjv7w9n7Y9lLVqJulj81JrqWw,312
|
20
20
|
plain/dev/views.py,sha256=r2Ivk7OXytpRhXq4DZpsb7FXNP9vzmEE3D5kLajYG4w,1073
|
21
|
-
plain_dev-0.
|
22
|
-
plain_dev-0.
|
23
|
-
plain_dev-0.
|
24
|
-
plain_dev-0.
|
25
|
-
plain_dev-0.
|
21
|
+
plain_dev-0.6.0.dist-info/LICENSE,sha256=cvKM3OlqHx3ijD6e34zsSUkPvzl-ya3Dd63A6EHL94U,1500
|
22
|
+
plain_dev-0.6.0.dist-info/METADATA,sha256=1kaH9Gal5Got6ltGlMJne_GI6Mqjd8Bz4CILkVujmTo,4663
|
23
|
+
plain_dev-0.6.0.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
|
24
|
+
plain_dev-0.6.0.dist-info/entry_points.txt,sha256=rBo-S4THn07f55UwHBuUhIbDhlUq3EzTOD8mIb5fGQg,99
|
25
|
+
plain_dev-0.6.0.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|