plain.dev 0.36.0__py3-none-any.whl → 0.38.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/AGENTS.md +3 -0
- plain/dev/CHANGELOG.md +20 -0
- plain/dev/alias.py +152 -0
- plain/dev/cli.py +4 -1
- {plain_dev-0.36.0.dist-info → plain_dev-0.38.0.dist-info}/METADATA +1 -1
- {plain_dev-0.36.0.dist-info → plain_dev-0.38.0.dist-info}/RECORD +9 -7
- {plain_dev-0.36.0.dist-info → plain_dev-0.38.0.dist-info}/WHEEL +0 -0
- {plain_dev-0.36.0.dist-info → plain_dev-0.38.0.dist-info}/entry_points.txt +0 -0
- {plain_dev-0.36.0.dist-info → plain_dev-0.38.0.dist-info}/licenses/LICENSE +0 -0
plain/dev/AGENTS.md
ADDED
plain/dev/CHANGELOG.md
CHANGED
@@ -1,5 +1,25 @@
|
|
1
1
|
# plain-dev changelog
|
2
2
|
|
3
|
+
## [0.38.0](https://github.com/dropseed/plain/releases/plain-dev@0.38.0) (2025-09-30)
|
4
|
+
|
5
|
+
### What's changed
|
6
|
+
|
7
|
+
- Added an `AGENTS.md` file with package-specific agent instructions for the `plain dev logs` command ([5841a3f](https://github.com/dropseed/plain/commit/5841a3fb0b))
|
8
|
+
|
9
|
+
### Upgrade instructions
|
10
|
+
|
11
|
+
- No changes required
|
12
|
+
|
13
|
+
## [0.37.0](https://github.com/dropseed/plain/releases/plain-dev@0.37.0) (2025-09-29)
|
14
|
+
|
15
|
+
### What's changed
|
16
|
+
|
17
|
+
- Added a `p` alias prompt that suggests setting up a shell alias for `uv run plain` to make command execution faster ([d913b44](https://github.com/dropseed/plain/commit/d913b44fab), [6632529](https://github.com/dropseed/plain/commit/663252925b))
|
18
|
+
|
19
|
+
### Upgrade instructions
|
20
|
+
|
21
|
+
- No changes required
|
22
|
+
|
3
23
|
## [0.36.0](https://github.com/dropseed/plain/releases/plain-dev@0.36.0) (2025-09-25)
|
4
24
|
|
5
25
|
### What's changed
|
plain/dev/alias.py
ADDED
@@ -0,0 +1,152 @@
|
|
1
|
+
import os
|
2
|
+
import subprocess
|
3
|
+
import sys
|
4
|
+
from functools import cached_property
|
5
|
+
from pathlib import Path
|
6
|
+
|
7
|
+
import click
|
8
|
+
|
9
|
+
|
10
|
+
class AliasManager:
|
11
|
+
"""Manages the 'p' alias for 'uv run plain'."""
|
12
|
+
|
13
|
+
MARKER_FILE = Path.home() / ".plain" / "dev" / ".alias_prompted"
|
14
|
+
ALIAS_COMMAND = "uv run plain"
|
15
|
+
ALIAS_NAME = "p"
|
16
|
+
|
17
|
+
@cached_property
|
18
|
+
def shell(self):
|
19
|
+
"""Detect the current shell."""
|
20
|
+
shell = os.environ.get("SHELL", "")
|
21
|
+
if "zsh" in shell:
|
22
|
+
return "zsh"
|
23
|
+
elif "bash" in shell:
|
24
|
+
return "bash"
|
25
|
+
elif "fish" in shell:
|
26
|
+
return "fish"
|
27
|
+
return None
|
28
|
+
|
29
|
+
@cached_property
|
30
|
+
def shell_config_file(self):
|
31
|
+
"""Get the appropriate shell configuration file."""
|
32
|
+
home = Path.home()
|
33
|
+
|
34
|
+
if self.shell == "zsh":
|
35
|
+
return home / ".zshrc"
|
36
|
+
elif self.shell == "bash":
|
37
|
+
# Check for .bash_aliases first (Ubuntu/Debian convention)
|
38
|
+
if (home / ".bash_aliases").exists():
|
39
|
+
return home / ".bash_aliases"
|
40
|
+
return home / ".bashrc"
|
41
|
+
elif self.shell == "fish":
|
42
|
+
return home / ".config" / "fish" / "config.fish"
|
43
|
+
|
44
|
+
return None
|
45
|
+
|
46
|
+
def _command_exists(self, command):
|
47
|
+
"""Check if a command exists in the system."""
|
48
|
+
try:
|
49
|
+
result = subprocess.run(
|
50
|
+
["which", command], capture_output=True, text=True, check=False
|
51
|
+
)
|
52
|
+
return result.returncode == 0
|
53
|
+
except Exception:
|
54
|
+
return False
|
55
|
+
|
56
|
+
def _alias_exists(self):
|
57
|
+
"""Check if the 'p' alias already exists."""
|
58
|
+
# First check if 'p' is already a command
|
59
|
+
if self._command_exists(self.ALIAS_NAME):
|
60
|
+
return True
|
61
|
+
|
62
|
+
# Check if alias is defined in shell
|
63
|
+
try:
|
64
|
+
# Try to run the alias to see if it exists
|
65
|
+
result = subprocess.run(
|
66
|
+
[self.shell, "-i", "-c", f"alias {self.ALIAS_NAME}"],
|
67
|
+
capture_output=True,
|
68
|
+
text=True,
|
69
|
+
check=False,
|
70
|
+
timeout=2,
|
71
|
+
)
|
72
|
+
return result.returncode == 0
|
73
|
+
except (subprocess.TimeoutExpired, Exception):
|
74
|
+
return False
|
75
|
+
|
76
|
+
def _add_alias_to_shell(self):
|
77
|
+
"""Add the alias to the shell configuration file."""
|
78
|
+
if not self.shell_config_file or not self.shell_config_file.exists():
|
79
|
+
return False
|
80
|
+
|
81
|
+
alias_line = f'alias {self.ALIAS_NAME}="{self.ALIAS_COMMAND}"'
|
82
|
+
comment = "# Added by Plain"
|
83
|
+
|
84
|
+
# Check if alias already in file
|
85
|
+
try:
|
86
|
+
with open(self.shell_config_file) as f:
|
87
|
+
content = f.read()
|
88
|
+
if alias_line in content:
|
89
|
+
return True
|
90
|
+
except Exception:
|
91
|
+
return False
|
92
|
+
|
93
|
+
# Add alias to file
|
94
|
+
try:
|
95
|
+
with open(self.shell_config_file, "a") as f:
|
96
|
+
f.write(f"\n{comment}\n{alias_line}\n")
|
97
|
+
|
98
|
+
click.secho(
|
99
|
+
f"✓ Added '{self.ALIAS_NAME}' alias to {self.shell_config_file.name}. Restart your shell!",
|
100
|
+
fg="green",
|
101
|
+
)
|
102
|
+
return True
|
103
|
+
except Exception as e:
|
104
|
+
click.secho(
|
105
|
+
f"Failed to add alias to {self.shell_config_file.name}: {e}", fg="red"
|
106
|
+
)
|
107
|
+
return False
|
108
|
+
|
109
|
+
def check_and_prompt(self):
|
110
|
+
"""Check if alias exists and prompt user to set it up if needed."""
|
111
|
+
# Only suggest if project uses uv (has uv.lock file)
|
112
|
+
if not Path("uv.lock").exists():
|
113
|
+
return
|
114
|
+
|
115
|
+
# Don't prompt if already configured
|
116
|
+
if self._alias_exists():
|
117
|
+
return
|
118
|
+
|
119
|
+
# Don't prompt if we've asked before
|
120
|
+
if self.MARKER_FILE.exists():
|
121
|
+
return
|
122
|
+
|
123
|
+
# Don't prompt for certain commands
|
124
|
+
if "--help" in sys.argv or "-h" in sys.argv:
|
125
|
+
return
|
126
|
+
|
127
|
+
# Mark that we've asked (do this first so we don't ask again even if they Ctrl+C)
|
128
|
+
self.MARKER_FILE.parent.mkdir(parents=True, exist_ok=True)
|
129
|
+
self.MARKER_FILE.touch()
|
130
|
+
|
131
|
+
click.echo()
|
132
|
+
click.secho("💡 Tip: ", fg="yellow", bold=True, nl=False)
|
133
|
+
click.echo(
|
134
|
+
f"Set up `{self.ALIAS_NAME}` as an alias to run commands faster (e.g., `{self.ALIAS_NAME} dev` instead of `uv run plain dev`)."
|
135
|
+
)
|
136
|
+
click.echo()
|
137
|
+
|
138
|
+
# Check if shell is supported
|
139
|
+
if not self.shell or not self.shell_config_file:
|
140
|
+
click.echo("To set this up manually, add to your shell config:")
|
141
|
+
click.echo(f' alias {self.ALIAS_NAME}="{self.ALIAS_COMMAND}"')
|
142
|
+
click.echo()
|
143
|
+
return
|
144
|
+
|
145
|
+
# Offer to set it up
|
146
|
+
prompt_text = f"Would you like to add this to {self.shell_config_file.name}?"
|
147
|
+
if click.confirm(prompt_text, default=False):
|
148
|
+
click.echo()
|
149
|
+
if self._add_alias_to_shell():
|
150
|
+
sys.exit(0) # Completely exit
|
151
|
+
|
152
|
+
click.echo()
|
plain/dev/cli.py
CHANGED
@@ -9,6 +9,7 @@ import click
|
|
9
9
|
from plain.cli import register_cli
|
10
10
|
from plain.runtime import APP_PATH, PLAIN_TEMP_PATH
|
11
11
|
|
12
|
+
from .alias import AliasManager
|
12
13
|
from .core import ENTRYPOINT_GROUP, DevProcess
|
13
14
|
from .services import ServicesProcess
|
14
15
|
|
@@ -119,7 +120,6 @@ class DevGroup(click.Group):
|
|
119
120
|
)
|
120
121
|
def cli(ctx, port, hostname, log_level, start, stop):
|
121
122
|
"""Start local development"""
|
122
|
-
|
123
123
|
if ctx.invoked_subcommand:
|
124
124
|
return
|
125
125
|
|
@@ -170,6 +170,9 @@ def cli(ctx, port, hostname, log_level, start, stop):
|
|
170
170
|
)
|
171
171
|
return
|
172
172
|
|
173
|
+
# Check and prompt for alias setup
|
174
|
+
AliasManager().check_and_prompt()
|
175
|
+
|
173
176
|
dev.setup(port=port, hostname=hostname, log_level=log_level)
|
174
177
|
returncode = dev.run()
|
175
178
|
if returncode:
|
@@ -1,7 +1,9 @@
|
|
1
|
-
plain/dev/
|
1
|
+
plain/dev/AGENTS.md,sha256=WOrdXNog-K3tXm1D_f6ZyyXi_amBGQ2gviKGaW8qtxA,101
|
2
|
+
plain/dev/CHANGELOG.md,sha256=sRZlqy0Azg4eaxkGkpKJnHNjXr6_qfXj5Q1mevPpYA4,6377
|
2
3
|
plain/dev/README.md,sha256=wsDVPGfvVG1k3CTf-SsGnzvHukhKrwRMgThYHMpdXSc,4802
|
3
4
|
plain/dev/__init__.py,sha256=9ByBOIdM8DebChjNz-RH2atdz4vWe8somlwNEsbhwh4,40
|
4
|
-
plain/dev/
|
5
|
+
plain/dev/alias.py,sha256=LWG01nUzu_4FFwg0jAVie7fwEwOiZD_6Q3xs7Krmjoo,4944
|
6
|
+
plain/dev/cli.py,sha256=HbN1Lc7Wfs5JC1iKUyIqin2m9UF0Iyirg4b4JLXBbOo,8501
|
5
7
|
plain/dev/core.py,sha256=OX5tUez2ac2q3ha9ylgU5y44USJc9mkn11J6o5AozXk,11496
|
6
8
|
plain/dev/debug.py,sha256=Ka84K8zUdF0kMYNyqiLYDrdzU1jU8LSOkts3hcw_Gok,1005
|
7
9
|
plain/dev/default_settings.py,sha256=uXWYORWP_aRDwXIFXdu5kHyiBFUZzARIJdhPeFaX35c,75
|
@@ -23,8 +25,8 @@ plain/dev/poncho/printer.py,sha256=1LhaQx55ujxmo-SSwQtzsh0bO6HL5q2_kiA0jLWEB-o,2
|
|
23
25
|
plain/dev/poncho/process.py,sha256=JJOKy-C6vMCg7-6JMCtu6C649h7HmOBSJqDP_hnX49I,2637
|
24
26
|
plain/dev/precommit/__init__.py,sha256=9ByBOIdM8DebChjNz-RH2atdz4vWe8somlwNEsbhwh4,40
|
25
27
|
plain/dev/precommit/cli.py,sha256=eAqe7rQGKJRbsICLrAabvNtRyTmWHkRo8XDo7I1DTkc,3285
|
26
|
-
plain_dev-0.
|
27
|
-
plain_dev-0.
|
28
|
-
plain_dev-0.
|
29
|
-
plain_dev-0.
|
30
|
-
plain_dev-0.
|
28
|
+
plain_dev-0.38.0.dist-info/METADATA,sha256=XqQi4Cl9wkiOgaMEA1MpVmKbsS_yGthrhbZhPP8YUmA,5304
|
29
|
+
plain_dev-0.38.0.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
30
|
+
plain_dev-0.38.0.dist-info/entry_points.txt,sha256=zrcTOiFk_MLKsnYVlwVP7aMm1XLEqq7w4EBkJ-3ge-g,114
|
31
|
+
plain_dev-0.38.0.dist-info/licenses/LICENSE,sha256=Cx4Dq9yR2fLHthf8Ke36B8QJvE1bZFXVzDIGE8wGzsY,4132
|
32
|
+
plain_dev-0.38.0.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|