Skip to content

Commit 25dfbc2

Browse files
committed
Merge subtree 'vimhelp' from 'vimhelp/master'
2 parents 0b64943 + 69841ab commit 25dfbc2

File tree

15 files changed

+895
-161
lines changed

15 files changed

+895
-161
lines changed

vimhelp/.gcloudignore

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,17 @@
1+
/.editorconfig
12
/.git
23
/.gitignore
34
/.gcloudignore
45
/.venv
56
/.ruff_cache
7+
/pyproject.toml
8+
/uv.lock
69
/scripts
710
/README.md
811
/LICENSE
912
/TODO
1013
/tasks.py
1114
/gunicorn.conf.dev.py
1215
__pycache__/
16+
*.egg-info/
1317
html/

vimhelp/.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
11
TODO
2+
/requirements.txt
23
/.venv/
34
__pycache__/
5+
*.egg-info/
6+
html/

vimhelp/app.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
runtime: python312
1+
runtime: python314
22

33
automatic_scaling:
44
max_instances: 2

vimhelp/pyproject.toml

Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,27 @@
11
[project]
22
name = "vimhelp"
33
version = "0.1"
4-
dynamic = ["dependencies"]
4+
requires-python = ">= 3.14"
5+
dependencies = [
6+
"Flask",
7+
"gevent",
8+
"geventhttpclient",
9+
"google-cloud-ndb",
10+
"google-cloud-secret-manager",
11+
"google-cloud-tasks",
12+
"gunicorn",
13+
]
514

615
[build-system]
716
requires = ["setuptools", "wheel"]
817
build-backend = "setuptools.build_meta"
918

10-
[tool.setuptools.dynamic]
11-
# Note that Google App Engine requires a requirements.txt file,
12-
# otherwise we'd just specify them directly in here.
13-
dependencies = { file = "requirements.txt" }
14-
15-
[tool.ruff]
16-
extend-exclude = [".pyre"]
17-
1819
[tool.ruff.lint]
1920
select = ["E", "F", "W", "I002", "N", "UP", "S", "B", "A", "C4", "DTZ", "SIM", "PTH", "PLE", "PLW", "RUF"]
2021
ignore = ["DTZ003", "PLW0603", "SIM102", "SIM108", "UP007"]
2122

2223
[tool.ruff.lint.per-file-ignores]
23-
"vimhelp/vimh2h.py" = ["E501", "PLW2901"]
24+
"vimhelp/vimh2h.py" = ["E501", "PLW2901", "S704"]
25+
26+
[tool.ruff.lint.flake8-builtins]
27+
builtins-allowed-modules = ["http"]

vimhelp/requirements.txt

Lines changed: 0 additions & 7 deletions
This file was deleted.

vimhelp/scripts/h2h.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,7 @@ def main():
8282

8383
app = flask.Flask(
8484
__name__,
85-
root_path=pathlib.Path(__file__).resolve().parent,
85+
root_path=str(pathlib.Path(__file__).resolve().parent),
8686
template_folder="../vimhelp/templates",
8787
)
8888
app.jinja_options["trim_blocks"] = True

vimhelp/tasks.py

Lines changed: 43 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# Use with https://www.pyinvoke.org/
22

3-
from invoke import call, task
3+
from invoke import task # ty:ignore[unresolved-import]
44

55
import os
66
import pathlib
@@ -10,9 +10,6 @@
1010
os.chdir(pathlib.Path(__file__).parent)
1111

1212

13-
VENV_DIR = pathlib.Path(".venv")
14-
REQ_TXT = pathlib.Path("requirements.txt")
15-
1613
PRIV_DIR = pathlib.Path("~/private").expanduser()
1714
STAGING_CREDENTIALS = PRIV_DIR / "gcloud-creds/vimhelp-staging-owner.json"
1815

@@ -24,7 +21,6 @@
2421
"PYTHONWARNINGS": (
2522
"default,"
2623
"ignore:unclosed:ResourceWarning:sys,"
27-
"ignore:Type google._upb._message:DeprecationWarning:importlib._bootstrap,"
2824
"ignore:This process (pid=:DeprecationWarning:gevent.os"
2925
),
3026
"VIMHELP_ENV": "dev",
@@ -34,34 +30,16 @@
3430
}
3531

3632

37-
@task(help={"lazy": "Only update venv if out-of-date wrt requirements.txt"})
38-
def venv(c, lazy=False):
39-
"""Populate virtualenv."""
40-
if not VENV_DIR.exists():
41-
c.run(f"python -m venv --upgrade-deps {VENV_DIR}")
42-
c.run(f"{VENV_DIR}/bin/pip install -U wheel")
43-
print("Created venv.")
44-
lazy = False
45-
if not lazy or REQ_TXT.stat().st_mtime > VENV_DIR.stat().st_mtime:
46-
c.run(f"{VENV_DIR}/bin/pip install -U --upgrade-strategy eager -r {REQ_TXT}")
47-
c.run(f"touch {VENV_DIR}")
48-
print("Updated venv.")
49-
else:
50-
print("venv was already up-to-date.")
51-
52-
53-
venv_lazy = call(venv, lazy=True)
54-
55-
5633
@task
5734
def lint(c):
58-
"""Run linter/formatter (ruff)."""
59-
c.run("ruff check .")
60-
c.run("ruff format --check")
35+
"""Run linters."""
36+
c.run("uv sync --locked")
37+
c.run("ruff check .", pty=True)
38+
c.run("ruff format --check", pty=True)
39+
c.run("ty check", pty=True)
6140

6241

6342
@task(
64-
pre=[venv_lazy],
6543
help={
6644
"gunicorn": "Run using gunicorn instead of 'flask run'",
6745
"tracemalloc": "Run with tracemalloc enabled",
@@ -71,21 +49,21 @@ def run(c, gunicorn=False, tracemalloc=False):
7149
"""Run app locally against staging database."""
7250
_ensure_private_mount(c)
7351
if gunicorn:
74-
cmd = f"{VENV_DIR}/bin/gunicorn -c gunicorn.conf.dev.py"
52+
cmd = "uv run gunicorn -c gunicorn.conf.dev.py"
7553
else:
76-
cmd = f"{VENV_DIR}/bin/flask --app vimhelp.webapp --debug run"
54+
cmd = "uv run flask --app vimhelp.webapp --debug run"
7755
if tracemalloc:
7856
env = DEV_ENV | {"PYTHONTRACEMALLOC": "1"}
7957
else:
8058
env = DEV_ENV
81-
c.run(cmd, env=env)
59+
c.run(cmd, env=env, pty=True)
8260

8361

84-
@task(pre=[venv_lazy])
62+
@task
8563
def show_routes(c):
8664
"""Show Flask routes."""
8765
_ensure_private_mount(c)
88-
c.run(f"{VENV_DIR}/bin/flask --app vimhelp.webapp --debug routes", env=DEV_ENV)
66+
c.run("uv run flask --app vimhelp.webapp --debug routes", env=DEV_ENV, pty=True)
8967

9068

9169
@task(
@@ -98,27 +76,46 @@ def show_routes(c):
9876
) # fmt: skip
9977
def deploy(c, target="staging", cron=False):
10078
"""Deploy app."""
79+
c.run("uv export -q --locked --no-emit-project -o requirements.txt")
10180
_ensure_private_mount(c)
102-
if target == "all":
103-
targets = "staging", "prod"
104-
else:
105-
targets = (target,)
106-
for t in targets:
107-
if t == "staging":
108-
cmd = f"gcloud app deploy --quiet --project={PROJECT_STAGING}"
109-
elif t == "prod":
110-
cmd = f"gcloud app deploy --project={PROJECT_PROD}"
111-
else:
112-
sys.exit(f"Invalid target name: '{t}'")
81+
target_map = {
82+
"all": (PROJECT_STAGING, PROJECT_PROD),
83+
"staging": (PROJECT_STAGING,),
84+
"prod": (PROJECT_PROD,),
85+
}
86+
projects = target_map.get(target)
87+
if projects is None:
88+
sys.exit(f"Invalid target name: '{target}'")
89+
for p in projects: # ty:ignore[not-iterable]
90+
cmd = f"gcloud app deploy --project={p} --quiet"
11391
if cron:
11492
cmd += " cron.yaml"
11593
c.run(cmd, pty=True)
11694

95+
old_vers = c.run(
96+
f"gcloud app versions list --project={p} --format='value(id)' "
97+
"--filter='traffic_split=0'"
98+
).stdout.split()
99+
if len(old_vers) > 0:
100+
print("Deleting old version(s):", ", ".join(old_vers))
101+
c.run(
102+
f"gcloud app versions delete --project={p} --quiet "
103+
+ " ".join(old_vers)
104+
)
105+
117106

118107
@task
119108
def clean(c):
120109
"""Clean up build artefacts."""
121-
for d in VENV_DIR, "__pycache__", "vimhelp/__pycache__", ".ruff_cache":
110+
to_remove = (
111+
".ruff_cache",
112+
".venv",
113+
"__pycache__",
114+
"requirements.txt",
115+
"vimhelp/__pycache__",
116+
"vimhelp.egg-info",
117+
)
118+
for d in to_remove:
122119
if pathlib.Path(d).exists():
123120
c.run(f"rm -rf {d}")
124121

@@ -127,7 +124,7 @@ def clean(c):
127124
def sh(c):
128125
"""Interactive shell with virtualenv and datastore available."""
129126
_ensure_private_mount(c)
130-
with c.prefix(f". {VENV_DIR}/bin/activate"):
127+
with c.prefix(". .venv/bin/activate"):
131128
c.run(os.getenv("SHELL", "bash"), env=DEV_ENV, pty=True)
132129
print("Exited vimhelp shell")
133130

0 commit comments

Comments
 (0)