Skip to content

Commit 7f9e02a

Browse files
Decentralized module loading and argument definitions
1 parent a405872 commit 7f9e02a

18 files changed

+380
-92
lines changed

.pre-commit-config.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ repos:
33
rev: v3.12.0
44
hooks:
55
- id: reorder-python-imports
6-
args: [--py311-plus, --add-import, "from __future__ import annotations"]
6+
args: [--py310-plus, --add-import, "from __future__ import annotations"]
77
- repo: https://github.com/psf/black
88
rev: 23.10.0
99
hooks:

devenv/commands/__init__.py

Whitespace-only changes.

devenv/bootstrap.py renamed to devenv/commands/bootstrap.py

Lines changed: 25 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
from __future__ import annotations
22

3-
import argparse
43
import os
54
import shutil
65
from collections.abc import Sequence
6+
from typing import cast
77

88
from devenv.constants import CI
99
from devenv.constants import EXTERNAL_CONTRIBUTOR
@@ -14,25 +14,33 @@
1414
from devenv.lib.config import Config
1515
from devenv.lib.config import initialize_config
1616
from devenv.lib.context import Context
17-
from devenv.lib.modules import DevModuleInfo
17+
from devenv.lib.modules import argument_fn
18+
from devenv.lib.modules import command
1819
from devenv.lib.modules import ExitCode
19-
20-
21-
def main(context: Context, argv: Sequence[str] | None = None) -> ExitCode:
22-
parser = argparse.ArgumentParser()
23-
parser.add_argument(
24-
"-d",
25-
"--default-config",
26-
action="append",
27-
help="Provide a default config value. e.g., -d coderoot:path/to/root",
20+
from devenv.lib.modules import ModuleDef
21+
from devenv.lib.modules import ParserFn
22+
23+
24+
@command("bootstrap", "Bootstraps the development environment.")
25+
@argument_fn(
26+
cast(
27+
ParserFn,
28+
lambda x: x.add_argument(
29+
"-d",
30+
"--default-config",
31+
metavar="config:value",
32+
required=False,
33+
action="append",
34+
help="Provide a default config value. e.g., -d coderoot:path/to/root",
35+
),
2836
)
29-
30-
args = parser.parse_args(argv)
37+
)
38+
def main(context: Context, argv: Sequence[str] | None = None) -> ExitCode:
39+
args = context["args"]
3140

3241
configs = {
3342
k: v for k, v in [i.split(":", 1) for i in args.default_config or []]
3443
}
35-
3644
if "coderoot" not in configs and "code_root" in context:
3745
configs["coderoot"] = context["code_root"]
3846

@@ -103,9 +111,8 @@ def main(context: Context, argv: Sequence[str] | None = None) -> ExitCode:
103111
return 0
104112

105113

106-
module_info = DevModuleInfo(
107-
action=main,
108-
name=__name__,
109-
command="bootstrap",
114+
module_info = ModuleDef(
115+
module_name=__name__,
116+
name="bootstrap",
110117
help="Bootstraps the development environment.",
111118
)

devenv/doctor.py renamed to devenv/commands/doctor.py

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,8 @@
1414
from typing import List
1515

1616
from devenv.lib.context import Context
17-
from devenv.lib.modules import DevModuleInfo
17+
from devenv.lib.modules import command
18+
from devenv.lib.modules import ModuleDef
1819
from devenv.lib.modules import require_repo
1920
from devenv.lib.repository import Repository
2021
from devenv.lib_check.types import checker
@@ -161,6 +162,7 @@ def attempt_fix(check: Check, executor: ThreadPoolExecutor) -> tuple[bool, str]:
161162
return False, f"Fix threw a runtime exception: {e}"
162163

163164

165+
@command("doctor", "Diagnose common issues, and optionally try to fix them.")
164166
@require_repo
165167
def main(context: Context, argv: Sequence[str] | None = None) -> int:
166168
parser = argparse.ArgumentParser()
@@ -232,9 +234,4 @@ def main(context: Context, argv: Sequence[str] | None = None) -> int:
232234
return 1
233235

234236

235-
module_info = DevModuleInfo(
236-
action=main,
237-
name=__name__,
238-
command="doctor",
239-
help="Diagnose common issues, and optionally try to fix them.",
240-
)
237+
module_info = ModuleDef(module_name=__name__, name="doctor", help="Diagnose common issues, and optionally try to fix them")

devenv/fetch.py renamed to devenv/commands/fetch.py

Lines changed: 13 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
from __future__ import annotations
22

3-
import argparse
43
import os
54
import sys
65
from collections.abc import Sequence
@@ -11,18 +10,16 @@
1110
from devenv.constants import homebrew_bin
1211
from devenv.lib import proc
1312
from devenv.lib.context import Context
14-
from devenv.lib.modules import DevModuleInfo
13+
from devenv.lib.modules import argument
14+
from devenv.lib.modules import command
1515
from devenv.lib.modules import ExitCode
16+
from devenv.lib.modules import ModuleDef
1617

1718

19+
@command("fetch", "Fetches a repository")
20+
@argument("repo", help="the repository to fetch")
1821
def main(context: Context, argv: Sequence[str] | None = None) -> ExitCode:
19-
parser = argparse.ArgumentParser()
20-
21-
parser.add_argument(
22-
"repo", type=str, help="the repository to fetch e.g., getsentry/sentry"
23-
)
24-
25-
args = parser.parse_args(argv)
22+
args = context["args"]
2623
code_root = context["code_root"]
2724

2825
if args.repo in ["ops", "getsentry/ops"]:
@@ -78,17 +75,20 @@ def main(context: Context, argv: Sequence[str] | None = None) -> ExitCode:
7875
)
7976

8077
else:
78+
if "/" not in args.repo:
79+
print("Repository names must be in the form of <owner>/<repo>")
80+
return 1
8181
fetch(code_root, args.repo)
8282

8383
return 0
8484

8585

8686
def fetch(
87-
coderoot: str, repo: str, auth: bool = True, sync: bool = True
87+
code_root: str, repo: str, auth: bool = True, sync: bool = True
8888
) -> None:
8989
org, slug = repo.split("/")
9090

91-
codepath = f"{coderoot}/{slug}"
91+
codepath = f"{code_root}/{slug}"
9292

9393
if os.path.exists(codepath):
9494
print(f"{codepath} already exists")
@@ -112,7 +112,7 @@ def fetch(
112112
(
113113
"git",
114114
"-C",
115-
coderoot,
115+
code_root,
116116
"clone",
117117
"--filter=blob:none",
118118
*additional_args,
@@ -124,6 +124,4 @@ def fetch(
124124
proc.run((sys.executable, "-P", "-m", "devenv", "sync"), cwd=codepath)
125125

126126

127-
module_info = DevModuleInfo(
128-
action=main, name=__name__, command="fetch", help="Fetches a respository"
129-
)
127+
module_info = ModuleDef(module_name=__name__, name="fetch", help="Fetches a repository")

devenv/pin_gha.py renamed to devenv/commands/pin_gha.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,8 @@
77
from functools import lru_cache
88

99
from devenv.lib.context import Context
10-
from devenv.lib.modules import DevModuleInfo
10+
from devenv.lib.modules import command
11+
from devenv.lib.modules import ModuleDef
1112

1213

1314
@lru_cache(maxsize=None)
@@ -38,6 +39,7 @@ def extract_repo(action: str) -> str:
3839
return f"{parts[0]}/{parts[1]}"
3940

4041

42+
@command("pin-gha", "Pins github actions.")
4143
def main(context: Context, argv: Sequence[str] | None = None) -> int:
4244
parser = argparse.ArgumentParser()
4345
parser.add_argument(
@@ -70,6 +72,4 @@ def main(context: Context, argv: Sequence[str] | None = None) -> int:
7072
return 0
7173

7274

73-
module_info = DevModuleInfo(
74-
action=main, name=__name__, command="pin_gha", help="Pins github actions."
75-
)
75+
module_info = ModuleDef(module_name=__name__, name="pin_gha", help="Pins github actions")

devenv/sync.py renamed to devenv/commands/sync.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,12 @@
55
from collections.abc import Sequence
66

77
from devenv.lib.context import Context
8-
from devenv.lib.modules import DevModuleInfo
8+
from devenv.lib.modules import command
9+
from devenv.lib.modules import ModuleDef
910
from devenv.lib.modules import require_repo
1011

1112

13+
@command("sync", "Resyncs the current project")
1214
@require_repo
1315
def main(context: Context, argv: Sequence[str] | None = None) -> int:
1416
repo = context["repo"]
@@ -33,6 +35,4 @@ def main(context: Context, argv: Sequence[str] | None = None) -> int:
3335
return module.main(context_compat) # type: ignore
3436

3537

36-
module_info = DevModuleInfo(
37-
action=main, name=__name__, command="sync", help="Resyncs the environment."
38-
)
38+
module_info = ModuleDef(module_name=__name__, name="sync", help="Resyncs the current project")

devenv/lib/config.py

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -60,13 +60,9 @@ def initialize_config(config_path: str, defaults: Config) -> None:
6060
else _val,
6161
)
6262

63-
if not CI:
63+
if not CI and opts:
6464
try:
65-
if opts:
66-
print(opts.prompt)
67-
else:
68-
print(f"{var}?")
69-
65+
print(opts.prompt)
7066
val = input(f" [{val}]: ") or val
7167
except EOFError:
7268
# noninterative, use the defaults

devenv/lib/context.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
from __future__ import annotations
22

3+
from argparse import Namespace
34
from typing import TypedDict
45

56
from devenv.lib.repository import Repository
@@ -9,3 +10,4 @@ class Context(TypedDict):
910
config_path: str
1011
code_root: str
1112
repo: Repository | None
13+
args: Namespace

0 commit comments

Comments
 (0)