plain.dev 0.27.1__py3-none-any.whl → 0.29.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 CHANGED
@@ -1,11 +1,11 @@
1
1
  import importlib
2
2
  import json
3
+ import multiprocessing
3
4
  import os
4
5
  import platform
5
6
  import signal
6
7
  import subprocess
7
8
  import sys
8
- import threading
9
9
  import time
10
10
  import tomllib
11
11
  from importlib.metadata import entry_points
@@ -223,21 +223,16 @@ class Dev:
223
223
  # If plain.models is installed (common) then we
224
224
  # will do a couple extra things before starting all of the app-related
225
225
  # processes (this way they don't all have to db-wait or anything)
226
+ process = None
226
227
  if find_spec("plain.models") is not None:
227
228
  # Use a custom signal to tell the main thread to add
228
229
  # the app processes once the db is ready
229
230
  signal.signal(signal.SIGUSR1, self.start_app)
230
231
 
231
- def _thread(env):
232
- subprocess.run(["plain", "models", "db-wait"], env=env, check=True)
233
- subprocess.run(["plain", "migrate", "--backup"], env=env, check=True)
234
- # preflight with db?
235
- os.kill(os.getpid(), signal.SIGUSR1)
236
-
237
- thread = threading.Thread(
238
- target=_thread, daemon=True, args=(self.plain_env,)
232
+ process = multiprocessing.Process(
233
+ target=_process_task, args=(self.plain_env,)
239
234
  )
240
- thread.start()
235
+ process.start()
241
236
  else:
242
237
  # Start the app processes immediately
243
238
  self.start_app(None, None)
@@ -253,6 +248,14 @@ class Dev:
253
248
  if services_pid:
254
249
  services_pid.rm()
255
250
 
251
+ # Make sure the process is terminated if it is still running
252
+ if process and process.is_alive():
253
+ os.killpg(os.getpgid(process.pid), signal.SIGTERM)
254
+ process.join(timeout=3)
255
+ if process.is_alive():
256
+ os.killpg(os.getpgid(process.pid), signal.SIGKILL)
257
+ process.join()
258
+
256
259
  return self.poncho.returncode
257
260
 
258
261
  def start_app(self, signum, frame):
@@ -349,24 +352,26 @@ class Dev:
349
352
  sys.exit(1)
350
353
 
351
354
  def set_csrf_and_allowed_hosts(self):
352
- csrf_trusted_origins = json.dumps(
353
- [
354
- self.url,
355
- ]
356
- )
357
- allowed_hosts = json.dumps([self.hostname])
358
-
359
- # Set environment variables
360
- self.plain_env["PLAIN_CSRF_TRUSTED_ORIGINS"] = csrf_trusted_origins
361
- self.custom_process_env["PLAIN_CSRF_TRUSTED_ORIGINS"] = csrf_trusted_origins
362
-
363
- self.plain_env["PLAIN_ALLOWED_HOSTS"] = allowed_hosts
364
- self.custom_process_env["PLAIN_ALLOWED_HOSTS"] = allowed_hosts
355
+ if "PLAIN_CSRF_TRUSTED_ORIGINS" not in os.environ:
356
+ csrf_trusted_origins = json.dumps(
357
+ [
358
+ self.url,
359
+ ]
360
+ )
361
+ self.plain_env["PLAIN_CSRF_TRUSTED_ORIGINS"] = csrf_trusted_origins
362
+ self.custom_process_env["PLAIN_CSRF_TRUSTED_ORIGINS"] = csrf_trusted_origins
363
+ click.secho(
364
+ f"Automatically set PLAIN_CSRF_TRUSTED_ORIGINS={csrf_trusted_origins}",
365
+ dim=True,
366
+ )
365
367
 
366
- click.secho(
367
- f"Automatically set PLAIN_ALLOWED_HOSTS={allowed_hosts} PLAIN_CSRF_TRUSTED_ORIGINS={csrf_trusted_origins}",
368
- dim=True,
369
- )
368
+ if "PLAIN_ALLOWED_HOSTS" not in os.environ:
369
+ allowed_hosts = json.dumps([self.hostname])
370
+ self.plain_env["PLAIN_ALLOWED_HOSTS"] = allowed_hosts
371
+ self.custom_process_env["PLAIN_ALLOWED_HOSTS"] = allowed_hosts
372
+ click.secho(
373
+ f"Automatically set PLAIN_ALLOWED_HOSTS={allowed_hosts}", dim=True
374
+ )
370
375
 
371
376
  def run_preflight(self):
372
377
  click.echo()
@@ -439,3 +444,16 @@ class Dev:
439
444
  **data.get("env", {}),
440
445
  }
441
446
  self.poncho.add_process(name, data["cmd"], env=env)
447
+
448
+
449
+ def _process_task(env):
450
+ # Make this process the leader of a new group which can be killed together if it doesn't finish
451
+ os.setsid()
452
+
453
+ subprocess.run(["plain", "models", "db-wait"], env=env, check=True)
454
+ subprocess.run(["plain", "migrate", "--backup"], env=env, check=True)
455
+
456
+ # preflight with db?
457
+
458
+ # Send SIGUSR1 to the parent process so the parent's handler is invoked
459
+ os.kill(os.getppid(), signal.SIGUSR1)
@@ -8,7 +8,7 @@ from plain.cli import register_cli
8
8
 
9
9
 
10
10
  @register_cli("contrib")
11
- @click.command("contribute")
11
+ @click.command("contribute", hidden=True)
12
12
  @click.option("--repo", default="../plain", help="Path to the plain repo")
13
13
  @click.option(
14
14
  "--reset", is_flag=True, help="Undo any changes to pyproject.toml and uv.lock"
plain/dev/requests.py CHANGED
@@ -137,10 +137,10 @@ class RequestLog:
137
137
  "method": request.method,
138
138
  "path": request.path,
139
139
  "full_path": request.get_full_path(),
140
- "querydict": request.POST.dict()
140
+ "querydict": request.data.dict()
141
141
  if request.method == "POST"
142
- else request.GET.dict(),
143
- "cookies": request.COOKIES,
142
+ else request.query_params.dict(),
143
+ "cookies": request.cookies,
144
144
  # files?
145
145
  "absolute_uri": request.build_absolute_uri(),
146
146
  "body": request.body.decode("utf-8"),
@@ -192,7 +192,7 @@ def should_capture_request(request):
192
192
 
193
193
  # This could be an attribute set on request or response
194
194
  # or something more dynamic
195
- if "querystats" in request.GET:
195
+ if "querystats" in request.query_params:
196
196
  return False
197
197
 
198
198
  return True
plain/dev/views.py CHANGED
@@ -11,10 +11,12 @@ class RequestsView(TemplateView):
11
11
  ctx = super().get_template_context()
12
12
  requestlogs = RequestLog.load_json_logs()
13
13
 
14
- if self.request.GET.get("log"):
14
+ if self.request.query_params.get("log"):
15
15
  try:
16
16
  requestlog = [
17
- x for x in requestlogs if x.get("name") == self.request.GET["log"]
17
+ x
18
+ for x in requestlogs
19
+ if x.get("name") == self.request.query_params["log"]
18
20
  ][0]
19
21
  except IndexError:
20
22
  requestlog = None
@@ -29,9 +31,9 @@ class RequestsView(TemplateView):
29
31
  return ctx
30
32
 
31
33
  def post(self):
32
- if self.request.POST.get("action") == "clear":
34
+ if self.request.data.get("action") == "clear":
33
35
  RequestLog.clear()
34
36
  return ResponseRedirect(self.request.path)
35
37
  else:
36
- RequestLog.replay_request(self.request.POST["log"])
38
+ RequestLog.replay_request(self.request.data["log"])
37
39
  return ResponseRedirect(".")
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: plain.dev
3
- Version: 0.27.1
3
+ Version: 0.29.0
4
4
  Summary: Local development tools for Plain.
5
5
  Author-email: Dave Gaeddert <dave.gaeddert@dropseed.dev>
6
6
  License-Expression: BSD-3-Clause
@@ -1,20 +1,20 @@
1
1
  plain/dev/README.md,sha256=EQJ9lF-JQ9KQWJZ_j6CD3jbRquOLgDRlIPbgT7A2gG4,3658
2
2
  plain/dev/__init__.py,sha256=nRX1B0Br8gmqhJLqo5Z9PqzReDahBtbmwH6C-7hzuls,103
3
- plain/dev/cli.py,sha256=z6xDeU1hcu3dTI55H7MllKZBQz4fnAO_Y-VoIKPLO7M,14843
3
+ plain/dev/cli.py,sha256=lyiIJveVedrO1MDwTlV-C-UYzMHR48q7MWEUODEQMUc,15605
4
4
  plain/dev/debug.py,sha256=Ka84K8zUdF0kMYNyqiLYDrdzU1jU8LSOkts3hcw_Gok,1005
5
5
  plain/dev/default_settings.py,sha256=uXWYORWP_aRDwXIFXdu5kHyiBFUZzARIJdhPeFaX35c,75
6
6
  plain/dev/entrypoints.py,sha256=diqNwA6eydUMtoO7p_rH-DtSYsw5-GBmjFe1Z5bHagc,579
7
7
  plain/dev/gunicorn_logging.json,sha256=yU23jzs5G4YGdDWBNiyAc3KypR4HirR6afIkD7w6DhU,1113
8
8
  plain/dev/mkcert.py,sha256=fm1U_UTGPREso6ZaP79WqEvd9uvA4lYWFo6fKhNglMM,3911
9
9
  plain/dev/pdb.py,sha256=4ru3rlIIyuYVXteyI7v42i4MmdBIjpJP0IJemBpf83A,3742
10
- plain/dev/requests.py,sha256=D1NX0qC8ADtf_zwsGMTp9aiE6Sh9QmoxFJCU_V8Wers,6839
10
+ plain/dev/requests.py,sha256=NH-_FYolAUbh2-m0x9hTdK6AS7HLo6cGETTpp6R-Wto,6857
11
11
  plain/dev/services.py,sha256=bfIXEVsot20cDbyIeRJ9xAiTTVxowHrLAiZM2aOMXDU,2845
12
12
  plain/dev/urls.py,sha256=6fyl-DvxDgKjUjpyhuLN8m6GisB8L-eH4rhYH_eRmGA,188
13
13
  plain/dev/utils.py,sha256=4wMzpvj1Is_c0QxhsTu34_P9wAYlzw4glNPfVtZr_0A,123
14
- plain/dev/views.py,sha256=r2Ivk7OXytpRhXq4DZpsb7FXNP9vzmEE3D5kLajYG4w,1073
14
+ plain/dev/views.py,sha256=yCZ_YmkJGCb3YYgElhzAPrA9V0X3lkiLD1-Ht1HjV7A,1131
15
15
  plain/dev/contribute/README.md,sha256=v9Ympugu2wvDEe_045WJnF1dmC4ZH7v_Bnxkpfaf_rM,329
16
16
  plain/dev/contribute/__init__.py,sha256=9ByBOIdM8DebChjNz-RH2atdz4vWe8somlwNEsbhwh4,40
17
- plain/dev/contribute/cli.py,sha256=jSfocR754VGMzcnb62zJA2lxxjry1Bdzupbsm3McgdY,3084
17
+ plain/dev/contribute/cli.py,sha256=YirzF4YCQoFhWS-JgQHNxqJIX9BY_m9lb3_ZdrI7sn4,3097
18
18
  plain/dev/poncho/__init__.py,sha256=MDOk2rhhoR3V-I-rg6tMHFeX60vTGJuQ14RI-_N6tQY,97
19
19
  plain/dev/poncho/color.py,sha256=Dk77inPR9qNc9vCaZOGk8W9skXfRgoUlxp_E6mhPNns,610
20
20
  plain/dev/poncho/compat.py,sha256=l66WZLR7kRpO8P8DI5-aUsbNlohPaXEurQ5xXESQYDs,1276
@@ -24,8 +24,8 @@ plain/dev/poncho/process.py,sha256=JJOKy-C6vMCg7-6JMCtu6C649h7HmOBSJqDP_hnX49I,2
24
24
  plain/dev/precommit/__init__.py,sha256=9ByBOIdM8DebChjNz-RH2atdz4vWe8somlwNEsbhwh4,40
25
25
  plain/dev/precommit/cli.py,sha256=KVHcG3Y_JZJNu3_MLIrO5s6yMYQfAArIU5L0hNWZUjg,3441
26
26
  plain/dev/templates/dev/requests.html,sha256=kQKJZq5L77juuL_t8UjcAehEU61U4RXNnKaAET-wAm8,7627
27
- plain_dev-0.27.1.dist-info/METADATA,sha256=CgZpO23_EYRFL2OX0AC8glbya4WORC1kPaduysWuq-c,4163
28
- plain_dev-0.27.1.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
29
- plain_dev-0.27.1.dist-info/entry_points.txt,sha256=zrcTOiFk_MLKsnYVlwVP7aMm1XLEqq7w4EBkJ-3ge-g,114
30
- plain_dev-0.27.1.dist-info/licenses/LICENSE,sha256=Cx4Dq9yR2fLHthf8Ke36B8QJvE1bZFXVzDIGE8wGzsY,4132
31
- plain_dev-0.27.1.dist-info/RECORD,,
27
+ plain_dev-0.29.0.dist-info/METADATA,sha256=I1CaEkxMtbFGR_dFf0JTMwbNNmw-2cafYs5-11CINC4,4163
28
+ plain_dev-0.29.0.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
29
+ plain_dev-0.29.0.dist-info/entry_points.txt,sha256=zrcTOiFk_MLKsnYVlwVP7aMm1XLEqq7w4EBkJ-3ge-g,114
30
+ plain_dev-0.29.0.dist-info/licenses/LICENSE,sha256=Cx4Dq9yR2fLHthf8Ke36B8QJvE1bZFXVzDIGE8wGzsY,4132
31
+ plain_dev-0.29.0.dist-info/RECORD,,