Final review of my code

import argparse
import secrets
import subprocess
import sys
from pathlib import Path
from typing import Any


class UserAbortException(Exception):
    pass


def execute_command(*args: str, should_capture_output: bool = False) -> str:
    cmd_output = subprocess.run(
        args,
        capture_output=should_capture_output,
        check=True,
        text=True,
    )
    return cmd_output.stdout


def count_lines(filepath: Path) -> int:
    with filepath.open(mode="r", encoding="utf-8") as file:
        return sum(1 for _line in file)


def random_line(filepath: Path) -> str:
    num_lines = count_lines(filepath)
    random_index = secrets.randbelow(num_lines)
    with filepath.open(mode="r", encoding="utf-8") as file:
        for index, line in enumerate(file):
            if index == random_index:
                return line.strip()
    err_msg = "Line not found"
    raise RuntimeError(err_msg)


def prompt_user_decision() -> None:
    choices = {"yes": "y", "exit": "e"}
    while True:
        decision = input("Continue?(y|e) ").lower()
        if decision not in choices.values():
            continue
        if decision == choices["yes"]:
            break
        if decision == choices["exit"]:
            reason = "The user is not ready."
            raise UserAbortException(reason)
        return


def check_args(arg_parser: Any, parsed_args: Any) -> None:
    if parsed_args.R and parsed_args.A:
        arg_parser.error("Arguments -R and -A can't be mixed!")
    if parsed_args.r and parsed_args.t:
        arg_parser.error("Arguments -r and -t can't be mixed!")
    if parsed_args.r and not parsed_args.f:
        arg_parser.error("The -f argument is required when -r is passed.")


def main() -> int:
    execute_command("echo", "Restarting the server")

    expected_string = "config = ~/"
    cmd_output = execute_command(
        "echo",
        "config = /tmp/",
        should_capture_output=True,
    )
    if expected_string not in cmd_output:
        execute_command("echo", "Option two is initiated.")
        prompt_user_decision()

    parser = argparse.ArgumentParser()
    parser.add_argument("-f", type=str, help="input file path")
    parser.add_argument("-u", type=int, help="...")
    parser.add_argument("-R", action="store_true", help="...")
    parser.add_argument("-A", action="store_true", help="...")
    parser.add_argument("-r", action="store_true", help="...")
    parser.add_argument("-t", action="store_true", help="...")
    parser.add_argument("-l", action="store_true", help="...")
    parser.add_argument("-s", action="store_true", help="...")
    parser.add_argument("-d", action="store_true", help="...")
    args = parser.parse_args()
    check_args(parser, args)

    if args.R:
        execute_command("echo", "...")

    if args.A:
        execute_command("echo", "...")

    if args.r:
        filepath = Path(args.f)
        cmd_arg = random_line(filepath)
        execute_command("echo", f"{cmd_arg}")

    if args.t:
        execute_command("echo", "...")

    if args.l:
        execute_command("echo", "...")

    if args.s:
        execute_command("echo", "...")

    if args.d:
        execute_command("echo", "...")

    execute_command("echo", "Stopping the server")

    return 0


if __name__ == "__main__":
    sys.exit(main())

What do you want help with? You have not asked any questions.

1 Like

Considering you don’t have any docstrings, help messages or explanation… I don’t think it would pass a final review.

Generally code that has at least basic docstrings for non-obvious methods/files is a bit easier to look at / review.

1 Like

This is the last time I can ask for a review of my code to make me a better programmer, that’s what I mean by a “final review” before I have to focus on Java and JavaScript. So I can’t spend any more time in my code. Thanks to all of you!