Skip to content

Commit

Permalink
feat: bench validate-dependencies command (frappe#1534)
Browse files Browse the repository at this point in the history
This validates all `frappe-dependencies` and exits with 1 if any of
specifications fail.

This will be internal feature for FC for now. If this works well we can
make the validation fail during install-app itself without requiring any
additional command/steps.
  • Loading branch information
ankush authored Feb 7, 2024
1 parent 1a42175 commit ab9b617
Show file tree
Hide file tree
Showing 3 changed files with 30 additions and 11 deletions.
22 changes: 11 additions & 11 deletions bench/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -308,7 +308,7 @@ def get_pyproject(self) -> Optional[dict]:
self.pyproject = get_pyproject(pyproject_path)
return self.pyproject

def validate_app_dependencies(self) -> None:
def validate_app_dependencies(self, throw=False) -> None:
pyproject = self.get_pyproject() or {}
deps: Optional[dict] = (
pyproject.get("tool", {}).get("bench", {}).get("frappe-dependencies")
Expand All @@ -317,7 +317,7 @@ def validate_app_dependencies(self) -> None:
return

for dep, version in deps.items():
validate_dependency(self, dep, version)
validate_dependency(self, dep, version, throw=throw)

"""
Get App Cache
Expand Down Expand Up @@ -489,16 +489,13 @@ def can_frappe_use_cached(app: App) -> bool:
return False


def validate_dependency(app: App, dep: str, req_version: str) -> None:
def validate_dependency(app: App, dep: str, req_version: str, throw=False) -> None:
dep_path = Path(app.bench.name) / "apps" / dep
if not dep_path.is_dir():
click.secho(
f"Required frappe-dependency '{dep}' not found. "
f"Aborting '{app.name}' installation. "
f"Please install '{dep}' first and retry",
fg="red",
)
sys.exit(1)
click.secho(f"Required frappe-dependency '{dep}' not found.", fg="yellow")
if throw:
sys.exit(1)
return

dep_version = get_dep_version(dep, dep_path)
if not dep_version:
Expand All @@ -508,9 +505,12 @@ def validate_dependency(app: App, dep: str, req_version: str) -> None:
click.secho(
f"Installed frappe-dependency '{dep}' version '{dep_version}' "
f"does not satisfy required version '{req_version}'. "
f"App '{app.name}' might not work as expected",
f"App '{app.name}' might not work as expected.",
fg="yellow",
)
if throw:
click.secho(f"Please install '{dep}{req_version}' first and retry", fg="red")
sys.exit(1)


def get_dep_version(dep: str, dep_path: Path) -> Optional[str]:
Expand Down
2 changes: 2 additions & 0 deletions bench/commands/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ def bench_command(bench_path="."):
new_app,
pip,
remove_app,
validate_dependencies,
)

bench_command.add_command(init)
Expand All @@ -56,6 +57,7 @@ def bench_command(bench_path="."):
bench_command.add_command(exclude_app_for_update)
bench_command.add_command(include_app_for_update)
bench_command.add_command(pip)
bench_command.add_command(validate_dependencies)


from bench.commands.update import (
Expand Down
17 changes: 17 additions & 0 deletions bench/commands/make.py
Original file line number Diff line number Diff line change
Expand Up @@ -253,3 +253,20 @@ def pip(ctx, args):

env_py = get_env_cmd("python")
os.execv(env_py, (env_py, "-m", "pip") + args)


@click.command(
"validate-dependencies",
help="Validates that all requirements specified in frappe-dependencies are met curently.",
)
@click.pass_context
def validate_dependencies(ctx):
"Validate all specified frappe-dependencies."
from bench.bench import Bench
from bench.app import App

bench = Bench(".")

for app_name in bench.apps:
app = App(app_name, bench=bench)
app.validate_app_dependencies(throw=True)

0 comments on commit ab9b617

Please sign in to comment.