Skip to content

Commit

Permalink
Add asdf
Browse files Browse the repository at this point in the history
  • Loading branch information
goFrendiAsgard committed Dec 1, 2024
1 parent a03b70b commit a91d8db
Show file tree
Hide file tree
Showing 10 changed files with 226 additions and 16 deletions.
6 changes: 6 additions & 0 deletions src/zrb/builtin/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,9 @@
from zrb.builtin.project.add.fastapp import add_fastapp_to_project
from zrb.builtin.project.create.create import create_project
from zrb.builtin.python import format_python_code
from zrb.builtin.setup.dev.asdf import setup_asdf
from zrb.builtin.setup.system.latex.ubuntu import setup_latex_on_ubuntu
from zrb.builtin.setup.system.ubuntu import setup_ubuntu
from zrb.builtin.shell.autocomplete.bash import make_bash_autocomplete
from zrb.builtin.shell.autocomplete.subcmd import get_shell_subcommands
from zrb.builtin.shell.autocomplete.zsh import make_zsh_autocomplete
Expand Down Expand Up @@ -41,3 +44,6 @@
assert todo_edit
assert todo_complete
assert todo_log
assert setup_ubuntu
assert setup_latex_on_ubuntu
assert setup_asdf
9 changes: 7 additions & 2 deletions src/zrb/builtin/group.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,9 +35,14 @@

setup_group = cli.add_group(Group(name="setup", description="🛠️ Setup"))
setup_system_group = setup_group.add_group(
Group(name="system", description="🛠️ Setup system")
Group(name="system", description="🔧 Setup system")
)
setup_latex_group = setup_system_group.add_group(
Group(name="latex", description="✍️ Setup LaTeX")
)
setup_dev_group = setup_group.add_group(
Group(name="dev", description="💻 Setup developer tools")
)
setup_dev_group = setup_group.add_group(Group(name="dev", description="🧑‍💻 Setup dev"))
setup_service_group = setup_group.add_group(
Group(name="services", description="🌐 Setup services")
)
93 changes: 93 additions & 0 deletions src/zrb/builtin/setup/dev/asdf.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
import os

from zrb.builtin.group import setup_dev_group
from zrb.builtin.setup.dev.asdf_helper import (
check_asdf_dir,
get_install_prerequisites_cmd,
setup_asdf_ps_config,
setup_asdf_sh_config,
)
from zrb.context.any_context import AnyContext
from zrb.input.bool_input import BoolInput
from zrb.input.option_input import OptionInput
from zrb.task.cmd_task import CmdTask
from zrb.task.make_task import make_task
from zrb.task.task import Task

install_asdf_prerequisites = CmdTask(
name="install-asdf-prerequisites",
input=[
OptionInput(
name="package-manager",
description="Your package manager",
prompt="Your package manager",
options=["apt", "dnf", "pacman", "zypper", "brew", "spack"],
default_str="apt",
),
BoolInput(
name="use-sudo",
description="Use sudo or not",
prompt="Need sudo",
default_str="yes",
),
],
cmd=get_install_prerequisites_cmd,
)


download_asdf = CmdTask(
name="download-asdf",
cmd="git clone https://github.com/asdf-vm/asdf.git ~/.asdf --branch v0.14.1",
execute_condition=check_asdf_dir,
)
install_asdf_prerequisites >> download_asdf


@make_task(
name="setup-asdf-on-bash",
input=BoolInput(
name="setup-bash",
description="Setup bash",
prompt="Setup bash",
default_str="yes",
),
execute_condition='{ctx.input["setup_bash"]}',
upstream=download_asdf,
)
def setup_asdf_on_bash(ctx: AnyContext):
setup_asdf_sh_config(os.path.expanduser(os.path.join("~", ".bashrc")))


@make_task(
name="setup-asdf-on-zsh",
input=BoolInput(
name="setup-zsh", description="Setup zsh", prompt="Setup zsh", default_str="yes"
),
execute_condition='{ctx.input["setup_zsh"]}',
upstream=download_asdf,
)
def setup_asdf_on_zsh(ctx: AnyContext):
setup_asdf_sh_config(os.path.expanduser(os.path.join("~", ".zshrc")))


@make_task(
name="setup-asdf-on-powershell",
input=BoolInput(
name="setup-powershell",
description="Setup powershell",
prompt="Setup powershell",
default_str="yes",
),
execute_condition='{ctx.input["setup_powershell"]}',
upstream=download_asdf,
)
def setup_asdf_on_powershell(ctx: AnyContext):
setup_asdf_ps_config(
os.path.expanduser(os.path.join("~", ".config", "powershell", "profile.ps1"))
)


setup_asdf = setup_dev_group.add_task(
Task(name="setup-asdf", description="🧰 Setup `asdf`."), alias="asdf"
)
setup_asdf << [setup_asdf_on_bash, setup_asdf_on_zsh, setup_asdf_on_powershell]
41 changes: 41 additions & 0 deletions src/zrb/builtin/setup/dev/asdf_helper.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import os

from zrb.context.any_context import AnyContext


def get_install_prerequisites_cmd(ctx: AnyContext) -> str:
package_manager: str = ctx.input["package-manager"]
if package_manager in ["brew", "spack"]:
cmd = "{package_manager} install coreutils curl git"
elif package_manager == "pacman":
cmd = "{package_manager} -S curl git"
else:
cmd = "{package_manager} install curl git"
use_sudo: bool = ctx.input["use-sudo"]
if use_sudo:
return "sudo {cmd}"
return cmd


def check_asdf_dir(_: AnyContext):
asdf_dir = os.path.expanduser(os.path.join("~", ".asdf"))
return os.path.isdir(asdf_dir)


def setup_asdf_sh_config(file_path: str):
_setup_asdf_config(file_path, '. "$HOME/.asdf/asdf.sh"')


def setup_asdf_ps_config(file_path: str):
_setup_asdf_config(file_path, '. "$HOME/.asdf/asdf.ps1"')


def _setup_asdf_config(file_path: str, asdf_config: str):
dir_path = os.path.dirname(file_path)
os.makedirs(dir_path, exist_ok=True)
with open(file_path, "r") as f:
content = f.read()
if asdf_config in content:
return
with open(file_path, "a") as f:
f.write(f"\n{asdf_config}\n")
18 changes: 18 additions & 0 deletions src/zrb/builtin/setup/system/latex/ubuntu.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
from zrb.builtin.group import setup_latex_group
from zrb.builtin.setup.system.ubuntu import setup_ubuntu
from zrb.task.cmd_task import CmdTask

setup_latex_on_ubuntu = setup_latex_group.add_task(
CmdTask(
name="setup-latex-on-ubuntu",
description="🐧 Setup LaTeX on Ubuntu",
cmd=[
"sudo apt install -y \\",
"texlive-full texlive-latex-base texlive-fonts-recommended \\",
"texlive-fonts-extra texlive-latex-extra",
],
render_cmd=False,
),
alias="ubuntu",
)
setup_ubuntu >> setup_latex_on_ubuntu
28 changes: 28 additions & 0 deletions src/zrb/builtin/setup/system/ubuntu.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
from zrb.builtin.group import setup_system_group
from zrb.task.cmd_task import CmdTask

update_ubuntu = CmdTask(name="update-ubuntu", cmd="sudo apt update", render_cmd=False)

upgrade_todo = CmdTask(
name="upgrade-ubuntu", cmd="sudo apt upgrade -y", render_cmd=False
)
update_ubuntu >> upgrade_todo

setup_ubuntu = setup_system_group.add_task(
CmdTask(
name="setup-ubuntu",
description="🐧 Setup ubuntu",
cmd=[
"sudo apt install -y \\",
"build-essential python3-distutils libssl-dev zlib1g-dev \\"
"libbz2-dev libreadline-dev libsqlite3-dev libpq-dev python3-dev \\",
"llvm libncurses5-dev libncursesw5-dev xz-utils tk-dev libffi-dev \\",
"liblzma-dev python3-openssl libblas-dev liblapack-dev rustc \\",
"golang gfortran fd-find ripgrep wget curl git ncat zip unzip \\",
"cmake make tree tmux zsh neovim xdotool xsel",
],
render_cmd=False,
),
alias="ubuntu",
)
upgrade_todo >> setup_ubuntu
3 changes: 3 additions & 0 deletions src/zrb/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,9 @@ def _get_log_level(level: str) -> int:
LOAD_BUILTIN = to_boolean(os.getenv("ZRB_LOAD_BUILTIN", "1"))
ENV_PREFIX = os.getenv("ZRB_ENV", "")
SHOW_PROMPT = to_boolean(os.getenv("ZRB_SHOW_PROMPT", "1"))
WARN_UNRECOMMENDED_COMMAND = to_boolean(
os.getenv("ZRB_WARN_UNRECOMMENDED_COMMAND", "1")
)
SESSION_LOG_DIR = os.getenv(
"ZRB_SESSION_LOG_DIR", os.path.expanduser(os.path.join("~", ".zrb-session"))
)
Expand Down
22 changes: 17 additions & 5 deletions src/zrb/task/cmd_task.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
from zrb.attr.type import BoolAttr, IntAttr, StrAttr
from zrb.cmd.cmd_result import CmdResult
from zrb.cmd.cmd_val import AnyCmdVal, CmdVal, SingleCmdVal
from zrb.config import DEFAULT_SHELL
from zrb.config import DEFAULT_SHELL, WARN_UNRECOMMENDED_COMMAND
from zrb.context.any_context import AnyContext
from zrb.env.any_env import AnyEnv
from zrb.input.any_input import AnyInput
Expand Down Expand Up @@ -33,6 +33,7 @@ def __init__(
remote_host: StrAttr | None = None,
render_remote_host: bool = True,
remote_port: IntAttr | None = None,
render_remote_port: bool = True,
remote_user: StrAttr | None = None,
render_remote_user: bool = True,
remote_password: StrAttr | None = None,
Expand All @@ -43,6 +44,7 @@ def __init__(
render_cmd: bool = True,
cwd: str | None = None,
render_cwd: bool = True,
warn_unrecommended_command: bool | None = None,
max_output_line: int = 1000,
max_error_line: int = 1000,
execute_condition: BoolAttr = True,
Expand Down Expand Up @@ -84,6 +86,7 @@ def __init__(
self._remote_host = remote_host
self._render_remote_host = render_remote_host
self._remote_port = remote_port
self._render_remote_port = render_remote_port
self._remote_user = remote_user
self._render_remote_user = render_remote_user
self._remote_password = remote_password
Expand All @@ -96,6 +99,7 @@ def __init__(
self._render_cwd = render_cwd
self._max_output_line = max_output_line
self._max_error_line = max_error_line
self._should_warn_unrecommended_command = warn_unrecommended_command

async def _exec_action(self, ctx: AnyContext) -> CmdResult:
"""Turn _cmd attribute into subprocess.Popen and execute it as task's action.
Expand All @@ -116,7 +120,8 @@ async def _exec_action(self, ctx: AnyContext) -> CmdResult:
env_map = self.__get_env_map(ctx)
ctx.log_debug(f"Environment map: {env_map}")
cmd_process = None
self.__warn_unrecommended_commands(ctx, shell, cmd_script)
if self._get_should_warn_unrecommended_commands():
self._check_unrecommended_commands(ctx, shell, cmd_script)
try:
ctx.log_info("Running script")
cmd_process = await asyncio.create_subprocess_exec(
Expand Down Expand Up @@ -152,10 +157,15 @@ async def _exec_action(self, ctx: AnyContext) -> CmdResult:
if cmd_process is not None and cmd_process.returncode is None:
cmd_process.terminate()

def __warn_unrecommended_commands(
def _get_should_warn_unrecommended_commands(self):
if self._should_warn_unrecommended_command is None:
return WARN_UNRECOMMENDED_COMMAND
return self._should_warn_unrecommended_command

def _check_unrecommended_commands(
self, ctx: AnyContext, shell: str, cmd_script: str
):
if "bash" in shell or "zsh" in shell:
if shell.endswith("bash") or shell.endswith("zsh"):
unrecommended_commands = check_unrecommended_commands(cmd_script)
if unrecommended_commands:
ctx.log_warning("The script contains unrecommended commands")
Expand Down Expand Up @@ -207,7 +217,9 @@ def _get_remote_host(self, ctx: AnyContext) -> str:
)

def _get_remote_port(self, ctx: AnyContext) -> int:
return get_int_attr(ctx, self._remote_port, 22, auto_render=True)
return get_int_attr(
ctx, self._remote_port, 22, auto_render=self._render_remote_port
)

def _get_remote_user(self, ctx: AnyContext) -> str:
return get_str_attr(
Expand Down
16 changes: 8 additions & 8 deletions src/zrb/task/rsync_task.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,13 +24,13 @@ def __init__(
remote_host: StrAttr | None = None,
auto_render_remote_host: bool = True,
remote_port: IntAttr | None = None,
auto_render_remote_port: bool = True,
render_remote_port: bool = True,
remote_user: StrAttr | None = None,
auto_render_remote_user: bool = True,
render_remote_user: bool = True,
remote_password: StrAttr | None = None,
auto_render_remote_password: bool = True,
render_remote_password: bool = True,
remote_ssh_key: StrAttr | None = None,
auto_render_remote_ssh_key: bool = True,
render_remote_ssh_key: bool = True,
remote_source_path: StrAttr | None = None,
render_remote_source_path: bool = True,
remote_destination_path: StrAttr | None = None,
Expand Down Expand Up @@ -63,13 +63,13 @@ def __init__(
remote_host=remote_host,
render_remote_host=auto_render_remote_host,
remote_port=remote_port,
auto_render_remote_port=auto_render_remote_port,
auto_render_remote_port=render_remote_port,
remote_user=remote_user,
render_remote_user=auto_render_remote_user,
render_remote_user=render_remote_user,
remote_password=remote_password,
render_remote_password=auto_render_remote_password,
render_remote_password=render_remote_password,
remote_ssh_key=remote_ssh_key,
render_remote_ssh_key=auto_render_remote_ssh_key,
render_remote_ssh_key=render_remote_ssh_key,
cwd=cwd,
render_cwd=auto_render_cwd,
max_output_line=max_output_line,
Expand Down
6 changes: 5 additions & 1 deletion src/zrb/util/string/format.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,12 @@


def fstring_format(template: str, data: dict[str, Any]) -> str:
# Escape any backslashes and quotes in the template
escaped_template = template.replace("\\", "\\\\").replace('"', '\\"')
# Construct the f-string expression
f_string_expr = f'f"{escaped_template}"'
# Safely evaluate the template as a Python expression
try:
return eval(f'f"""{template}"""', {}, data)
return eval(f_string_expr, {}, data)
except Exception as e:
raise ValueError(f"Failed to parse template: {template}: {e}")

0 comments on commit a91d8db

Please sign in to comment.