2
0
mirror of https://github.com/frappe/bench.git synced 2024-09-27 22:39:03 +00:00

Merge pull request #1334 from gavindsouza/better-cli-resolution

refactor(cli): Commands Resolution
This commit is contained in:
gavin 2022-07-27 14:37:16 +05:30 committed by GitHub
commit a481934d53
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 82 additions and 40 deletions

View File

@ -1,6 +1,8 @@
# imports - standard imports
import atexit
from contextlib import contextmanager
import json
from logging import Logger
import os
import pwd
import sys
@ -25,7 +27,7 @@ from bench.utils import (
is_root,
log,
setup_logging,
parse_sys_argv,
get_cmd_from_sysargv,
)
from bench.utils.bench import get_env_cmd
@ -35,23 +37,41 @@ verbose = False
is_envvar_warn_set = None
from_command_line = False # set when commands are executed via the CLI
bench.LOG_BUFFER = []
sys_argv = None
change_uid_msg = "You should not run this command as root"
src = os.path.dirname(__file__)
@contextmanager
def execute_cmd(check_for_update=True, command: str = None, logger: Logger = None):
if check_for_update:
atexit.register(check_latest_version)
try:
yield
except BaseException as e:
return_code = getattr(e, "code", 1)
if isinstance(e, Exception):
click.secho(f"ERROR: {e}", fg="red")
if return_code:
logger.warning(f"{command} executed with exit code {return_code}")
raise e
def cli():
global from_command_line, bench_config, is_envvar_warn_set, verbose, sys_argv
global from_command_line, bench_config, is_envvar_warn_set, verbose
from_command_line = True
command = " ".join(sys.argv)
argv = set(sys.argv)
is_envvar_warn_set = not (os.environ.get("BENCH_DEVELOPER") or os.environ.get("CI"))
is_cli_command = len(sys.argv) > 1 and not argv.intersection({"src", "--version"})
sys_argv = parse_sys_argv()
cmd_from_sys = get_cmd_from_sysargv()
if "--verbose" in sys_argv.options:
if "--verbose" in argv:
verbose = True
change_working_directory()
@ -69,8 +89,8 @@ def cli():
if (
is_envvar_warn_set
and is_cli_command
and is_dist_editable(bench.PROJECT_NAME)
and not bench_config.get("developer_mode")
and is_dist_editable(bench.PROJECT_NAME)
):
log(
"bench is installed in editable mode!\n\nThis is not the recommended mode"
@ -89,36 +109,30 @@ def cli():
):
log("Command not being executed in bench directory", level=3)
if in_bench and len(sys.argv) > 1:
if sys.argv[1] == "--help":
print(click.Context(bench_command).get_help())
if len(sys.argv) == 1 or sys.argv[1] == "--help":
print(click.Context(bench_command).get_help())
if in_bench:
print(get_frappe_help())
return
return
if (
sys_argv.commands.intersection(get_cached_frappe_commands())
or sys_argv.commands.intersection(get_frappe_commands())
):
_opts = [x.opts + x.secondary_opts for x in bench_command.params]
opts = {item for sublist in _opts for item in sublist}
# handle usages like `--use-feature='feat-x'` and `--use-feature 'feat-x'`
if cmd_from_sys and cmd_from_sys.split("=", 1)[0].strip() in opts:
bench_command()
if cmd_from_sys in bench_command.commands:
with execute_cmd(check_for_update=not is_cli_command, command=command, logger=logger):
bench_command()
if in_bench:
if cmd_from_sys in get_frappe_commands():
frappe_cmd()
if sys.argv[1] in Bench(".").apps:
else:
app_cmd()
if not is_cli_command:
atexit.register(check_latest_version)
try:
bench_command()
except BaseException as e:
return_code = getattr(e, "code", 1)
if isinstance(e, Exception):
click.secho(f"ERROR: {e}", fg="red")
if return_code:
logger.warning(f"{command} executed with exit code {return_code}")
raise e
bench_command()
def check_uid():

View File

@ -165,7 +165,7 @@ def which(executable: str, raise_err: bool = False) -> str:
return exec_
def setup_logging(bench_path=".") -> "logger":
def setup_logging(bench_path=".") -> logging.Logger:
LOG_LEVEL = 15
logging.addLevelName(LOG_LEVEL, "LOG")
@ -529,13 +529,41 @@ class _dict(dict):
return _dict(dict(self).copy())
def parse_sys_argv():
sys_argv = _dict(options=set(), commands=set())
def get_cmd_from_sysargv():
"""Identify and segregate tokens to options and command
for c in sys.argv[1:]:
if c.startswith("-"):
sys_argv.options.add(c)
else:
sys_argv.commands.add(c)
For Command: `bench --profile --site frappeframework.com migrate --no-backup`
sys.argv: ["/home/frappe/.local/bin/bench", "--profile", "--site", "frappeframework.com", "migrate", "--no-backup"]
Actual command run: migrate
return sys_argv
"""
# context is passed as options to frappe's bench_helper
from bench.bench import Bench
frappe_context = _dict(
params={"--site"},
flags={"--verbose", "--profile", "--force"}
)
cmd_from_ctx = None
sys_argv = sys.argv[1:]
skip_next = False
for arg in sys_argv:
if skip_next:
skip_next = False
continue
if arg in frappe_context.flags:
continue
elif arg in frappe_context.params:
skip_next = True
continue
if sys_argv.index(arg) == 0 and arg in Bench(".").apps:
continue
cmd_from_ctx = arg
break
return cmd_from_ctx