plain.dev 0.24.0__tar.gz → 0.26.0__tar.gz

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.
Files changed (33) hide show
  1. {plain_dev-0.24.0 → plain_dev-0.26.0}/PKG-INFO +1 -1
  2. {plain_dev-0.24.0 → plain_dev-0.26.0}/plain/dev/cli.py +75 -63
  3. {plain_dev-0.24.0 → plain_dev-0.26.0}/plain/dev/services.py +44 -14
  4. {plain_dev-0.24.0 → plain_dev-0.26.0}/pyproject.toml +1 -1
  5. plain_dev-0.24.0/plain/dev/pid.py +0 -20
  6. {plain_dev-0.24.0 → plain_dev-0.26.0}/.gitignore +0 -0
  7. {plain_dev-0.24.0 → plain_dev-0.26.0}/LICENSE +0 -0
  8. {plain_dev-0.24.0 → plain_dev-0.26.0}/README.md +0 -0
  9. {plain_dev-0.24.0 → plain_dev-0.26.0}/plain/dev/README.md +0 -0
  10. {plain_dev-0.24.0 → plain_dev-0.26.0}/plain/dev/__init__.py +0 -0
  11. {plain_dev-0.24.0 → plain_dev-0.26.0}/plain/dev/contribute/README.md +0 -0
  12. {plain_dev-0.24.0 → plain_dev-0.26.0}/plain/dev/contribute/__init__.py +0 -0
  13. {plain_dev-0.24.0 → plain_dev-0.26.0}/plain/dev/contribute/cli.py +0 -0
  14. {plain_dev-0.24.0 → plain_dev-0.26.0}/plain/dev/debug.py +0 -0
  15. {plain_dev-0.24.0 → plain_dev-0.26.0}/plain/dev/default_settings.py +0 -0
  16. {plain_dev-0.24.0 → plain_dev-0.26.0}/plain/dev/entrypoints.py +0 -0
  17. {plain_dev-0.24.0 → plain_dev-0.26.0}/plain/dev/gunicorn_logging.json +0 -0
  18. {plain_dev-0.24.0 → plain_dev-0.26.0}/plain/dev/mkcert.py +0 -0
  19. {plain_dev-0.24.0 → plain_dev-0.26.0}/plain/dev/pdb.py +0 -0
  20. {plain_dev-0.24.0 → plain_dev-0.26.0}/plain/dev/poncho/__init__.py +0 -0
  21. {plain_dev-0.24.0 → plain_dev-0.26.0}/plain/dev/poncho/color.py +0 -0
  22. {plain_dev-0.24.0 → plain_dev-0.26.0}/plain/dev/poncho/compat.py +0 -0
  23. {plain_dev-0.24.0 → plain_dev-0.26.0}/plain/dev/poncho/manager.py +0 -0
  24. {plain_dev-0.24.0 → plain_dev-0.26.0}/plain/dev/poncho/printer.py +0 -0
  25. {plain_dev-0.24.0 → plain_dev-0.26.0}/plain/dev/poncho/process.py +0 -0
  26. {plain_dev-0.24.0 → plain_dev-0.26.0}/plain/dev/precommit/__init__.py +0 -0
  27. {plain_dev-0.24.0 → plain_dev-0.26.0}/plain/dev/precommit/cli.py +0 -0
  28. {plain_dev-0.24.0 → plain_dev-0.26.0}/plain/dev/requests.py +0 -0
  29. {plain_dev-0.24.0 → plain_dev-0.26.0}/plain/dev/templates/dev/requests.html +0 -0
  30. {plain_dev-0.24.0 → plain_dev-0.26.0}/plain/dev/urls.py +0 -0
  31. {plain_dev-0.24.0 → plain_dev-0.26.0}/plain/dev/utils.py +0 -0
  32. {plain_dev-0.24.0 → plain_dev-0.26.0}/plain/dev/views.py +0 -0
  33. {plain_dev-0.24.0 → plain_dev-0.26.0}/tests/settings.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: plain.dev
3
- Version: 0.24.0
3
+ Version: 0.26.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
@@ -19,7 +19,6 @@ from plain.cli import register_cli
19
19
  from plain.runtime import APP_PATH, settings
20
20
 
21
21
  from .mkcert import MkcertManager
22
- from .pid import Pid
23
22
  from .poncho.manager import Manager as PonchoManager
24
23
  from .poncho.printer import Printer
25
24
  from .services import Services
@@ -104,7 +103,11 @@ def debug():
104
103
  @cli.command()
105
104
  def services():
106
105
  """Start additional services defined in pyproject.toml"""
107
- Services().run()
106
+ _services = Services()
107
+ if _services.are_running():
108
+ click.secho("Services already running", fg="yellow")
109
+ return
110
+ _services.run()
108
111
 
109
112
 
110
113
  @cli.command()
@@ -154,65 +157,59 @@ class Dev:
154
157
  self.poncho = PonchoManager(printer=Printer(lambda s: self.console.out(s)))
155
158
 
156
159
  def run(self):
157
- pid = Pid()
158
- pid.write()
159
-
160
- try:
161
- mkcert_manager = MkcertManager()
162
- mkcert_manager.setup_mkcert(install_path=Path.home() / ".plain" / "dev")
163
- self.ssl_cert_path, self.ssl_key_path = mkcert_manager.generate_certs(
164
- domain=self.hostname,
165
- storage_path=Path(settings.PLAIN_TEMP_PATH) / "dev" / "certs",
166
- )
160
+ mkcert_manager = MkcertManager()
161
+ mkcert_manager.setup_mkcert(install_path=Path.home() / ".plain" / "dev")
162
+ self.ssl_cert_path, self.ssl_key_path = mkcert_manager.generate_certs(
163
+ domain=self.hostname,
164
+ storage_path=Path(settings.PLAIN_TEMP_PATH) / "dev" / "certs",
165
+ )
167
166
 
168
- self.symlink_plain_src()
169
- self.modify_hosts_file()
170
- self.set_csrf_and_allowed_hosts()
171
- self.run_preflight()
172
-
173
- # Processes for poncho to run simultaneously
174
- self.add_gunicorn()
175
- self.add_entrypoints()
176
- self.add_pyproject_run()
177
- self.add_services()
178
-
179
- click.secho("\nStarting dev...", italic=True, dim=True)
180
-
181
- if self.tunnel_url:
182
- status_bar = Columns(
183
- [
184
- Text.from_markup(
185
- f"[bold]Tunnel[/bold] [underline][link={self.tunnel_url}]{self.tunnel_url}[/link][/underline]"
186
- ),
187
- Text.from_markup(
188
- f"[dim][bold]Server[/bold] [link={self.url}]{self.url}[/link][/dim]"
189
- ),
190
- Text.from_markup(
191
- "[dim][bold]Ctrl+C[/bold] to stop[/dim]",
192
- justify="right",
193
- ),
194
- ],
195
- expand=True,
196
- )
197
- else:
198
- status_bar = Columns(
199
- [
200
- Text.from_markup(
201
- f"[bold]Server[/bold] [underline][link={self.url}]{self.url}[/link][/underline]"
202
- ),
203
- Text.from_markup(
204
- "[dim][bold]Ctrl+C[/bold] to stop[/dim]", justify="right"
205
- ),
206
- ],
207
- expand=True,
208
- )
167
+ self.symlink_plain_src()
168
+ self.modify_hosts_file()
169
+ self.set_csrf_and_allowed_hosts()
170
+ self.run_preflight()
171
+
172
+ # Processes for poncho to run simultaneously
173
+ self.add_gunicorn()
174
+ self.add_entrypoints()
175
+ self.add_pyproject_run()
176
+ self.add_services()
177
+
178
+ click.secho("\nStarting dev...", italic=True, dim=True)
179
+
180
+ if self.tunnel_url:
181
+ status_bar = Columns(
182
+ [
183
+ Text.from_markup(
184
+ f"[bold]Tunnel[/bold] [underline][link={self.tunnel_url}]{self.tunnel_url}[/link][/underline]"
185
+ ),
186
+ Text.from_markup(
187
+ f"[dim][bold]Server[/bold] [link={self.url}]{self.url}[/link][/dim]"
188
+ ),
189
+ Text.from_markup(
190
+ "[dim][bold]Ctrl+C[/bold] to stop[/dim]",
191
+ justify="right",
192
+ ),
193
+ ],
194
+ expand=True,
195
+ )
196
+ else:
197
+ status_bar = Columns(
198
+ [
199
+ Text.from_markup(
200
+ f"[bold]Server[/bold] [underline][link={self.url}]{self.url}[/link][/underline]"
201
+ ),
202
+ Text.from_markup(
203
+ "[dim][bold]Ctrl+C[/bold] to stop[/dim]", justify="right"
204
+ ),
205
+ ],
206
+ expand=True,
207
+ )
209
208
 
210
- with self.console.status(status_bar):
211
- self.poncho.loop()
209
+ with self.console.status(status_bar):
210
+ self.poncho.loop()
212
211
 
213
- return self.poncho.returncode
214
- finally:
215
- pid.rm()
212
+ return self.poncho.returncode
216
213
 
217
214
  def symlink_plain_src(self):
218
215
  """Symlink the plain package into .plain so we can look at it easily"""
@@ -221,12 +218,21 @@ class Dev:
221
218
  ).parent.parent
222
219
  if not settings.PLAIN_TEMP_PATH.exists():
223
220
  settings.PLAIN_TEMP_PATH.mkdir()
221
+
224
222
  symlink_path = settings.PLAIN_TEMP_PATH / "src"
225
223
 
226
- # Remove a broken symlink if it changed
224
+ # The symlink is broken
227
225
  if symlink_path.is_symlink() and not symlink_path.exists():
228
226
  symlink_path.unlink()
229
227
 
228
+ # The symlink exists but points to the wrong place
229
+ if (
230
+ symlink_path.is_symlink()
231
+ and symlink_path.exists()
232
+ and symlink_path.resolve() != plain_path
233
+ ):
234
+ symlink_path.unlink()
235
+
230
236
  if plain_path.exists() and not symlink_path.exists():
231
237
  symlink_path.symlink_to(plain_path)
232
238
 
@@ -329,6 +335,8 @@ class Dev:
329
335
  str(self.ssl_cert_path),
330
336
  "--keyfile",
331
337
  str(self.ssl_key_path),
338
+ "--threads",
339
+ "4",
332
340
  "--reload",
333
341
  "plain.wsgi:app",
334
342
  "--timeout",
@@ -354,10 +362,6 @@ class Dev:
354
362
  else:
355
363
  runserver_cmd = gunicorn
356
364
 
357
- if "WEB_CONCURRENCY" not in self.plain_env:
358
- # Default to two workers to prevent lockups
359
- self.plain_env["WEB_CONCURRENCY"] = "2"
360
-
361
365
  self.poncho.add_process("plain", runserver_cmd, env=self.plain_env)
362
366
 
363
367
  def add_entrypoints(self):
@@ -388,6 +392,14 @@ class Dev:
388
392
 
389
393
  def add_services(self):
390
394
  """Services are things that also run during tests (like a database), and are critical for the app to function."""
395
+
396
+ if Services.are_running():
397
+ click.secho("Services already running", fg="yellow")
398
+ return
399
+
400
+ # TODO need to set services pid here somehow...
401
+
402
+ # Split each service into a separate process
391
403
  services = Services.get_services(APP_PATH.parent)
392
404
  for name, data in services.items():
393
405
  env = {
@@ -7,13 +7,29 @@ from pathlib import Path
7
7
 
8
8
  import click
9
9
 
10
- from plain.runtime import APP_PATH
10
+ from plain.runtime import APP_PATH, settings
11
11
 
12
- from .pid import Pid
13
12
  from .poncho.manager import Manager as PonchoManager
14
13
  from .utils import has_pyproject_toml
15
14
 
16
15
 
16
+ class ServicesPid:
17
+ def __init__(self):
18
+ self.pidfile = settings.PLAIN_TEMP_PATH / "dev" / "services.pid"
19
+
20
+ def write(self):
21
+ pid = os.getpid()
22
+ self.pidfile.parent.mkdir(parents=True, exist_ok=True)
23
+ with self.pidfile.open("w+") as f:
24
+ f.write(str(pid))
25
+
26
+ def rm(self):
27
+ self.pidfile.unlink()
28
+
29
+ def exists(self):
30
+ return self.pidfile.exists()
31
+
32
+
17
33
  class Services:
18
34
  @staticmethod
19
35
  def get_services(root):
@@ -33,25 +49,39 @@ class Services:
33
49
  def __init__(self):
34
50
  self.poncho = PonchoManager()
35
51
 
36
- def run(self):
37
- services = self.get_services(APP_PATH.parent)
38
- for name, data in services.items():
39
- env = {
40
- **os.environ,
41
- "PYTHONUNBUFFERED": "true",
42
- **data.get("env", {}),
43
- }
44
- self.poncho.add_process(name, data["cmd"], env=env)
52
+ @staticmethod
53
+ def are_running():
54
+ pid = ServicesPid()
55
+ return pid.exists()
45
56
 
46
- self.poncho.loop()
57
+ def run(self):
58
+ # Each user of Services will have to check if it is running by:
59
+ # - using the context manager (with Services())
60
+ # - calling are_running() directly
61
+ pid = ServicesPid()
62
+ pid.write()
63
+
64
+ try:
65
+ services = self.get_services(APP_PATH.parent)
66
+ for name, data in services.items():
67
+ env = {
68
+ **os.environ,
69
+ "PYTHONUNBUFFERED": "true",
70
+ **data.get("env", {}),
71
+ }
72
+ self.poncho.add_process(name, data["cmd"], env=env)
73
+
74
+ self.poncho.loop()
75
+ finally:
76
+ pid.rm()
47
77
 
48
78
  def __enter__(self):
49
79
  if not self.get_services(APP_PATH.parent):
50
80
  # No-op if no services are defined
51
81
  return
52
82
 
53
- if Pid().exists():
54
- click.secho("Services already running in `plain dev` command", fg="yellow")
83
+ if self.are_running():
84
+ click.secho("Services already running", fg="yellow")
55
85
  return
56
86
 
57
87
  print("Starting `plain dev services`")
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "plain.dev"
3
- version = "0.24.0"
3
+ version = "0.26.0"
4
4
  description = "Local development tools for Plain."
5
5
  authors = [{name = "Dave Gaeddert", email = "dave.gaeddert@dropseed.dev"}]
6
6
  license = "BSD-3-Clause"
@@ -1,20 +0,0 @@
1
- import os
2
-
3
- from plain.runtime import settings
4
-
5
-
6
- class Pid:
7
- def __init__(self):
8
- self.pidfile = settings.PLAIN_TEMP_PATH / "dev.pid"
9
-
10
- def write(self):
11
- pid = os.getpid()
12
- self.pidfile.parent.mkdir(parents=True, exist_ok=True)
13
- with self.pidfile.open("w+") as f:
14
- f.write(str(pid))
15
-
16
- def rm(self):
17
- self.pidfile.unlink()
18
-
19
- def exists(self):
20
- return self.pidfile.exists()
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes