So I'm trying to make a CLI but I'm having some errors with the 'cd' command. I can't access the 'target_path' variable from my cd command. Here's the code for the CLI:
import os, colorama
ERROR_COLOR = colorama.Back.RED + colorama.Fore.BLACK
user = os.getlogin()
target_path = f'C:\\Users\\{user}'
class Commands:
def __init__(self):
raise RuntimeError("Cannot instantiate class 'Commands'")
@staticmethod
def help(cmd=None):
cmd_help_msgs = {
'help': \
"""
HELP:
USAGE:
help [command: str]
DESCRIPTION:
Prints out the description and usage of a command.
If command is not passed, it prints out the help messages of all commands
""",
'cls': \
"""
CLS:
USAGE:
cls
DESCRIPTION:
Clears the terminal
""",
'exit': \
"""
EXIT:
USAGE:
exit
DESCRITPION:
Quits the program
""",
'echo': \
"""
ECHO:
USAGE:
echo <msg: str>
DESCRIPTION:
Prints out msg
"""
}
help_msg = f"""
IMPORTANT: [] = optional parameter, <> = mandatory parameter
COMMANDS:
"""
if cmd is None:
print(help_msg, end='')
for val in cmd_help_msgs.values():
print(val, end='')
else:
try:
print(help_msg, end='')
print(cmd_help_msgs[cmd])
except:
print(f"{ERROR_COLOR}'{cmd}' is not recognized as a valid command! Do 'help' to see all valid commands{colorama.Style.RESET_ALL}")
return
print('\n')
@staticmethod
def cls():
os.system('cls')
@staticmethod
def exit():
exit(0)
@staticmethod
def echo(msg=''):
if msg == '':
print(ERROR_COLOR + "Missing required argument 'msg'" + colorama.Style.RESET_ALL)
return
print(msg)
@staticmethod
def cd(directory=''):
if directory == '':
print(target_path)
return
if directory[1] != ':':
if os.path.exists(target_path + directory) and os.path.isdir(target_path + directory):
target_path += directory
else:
print(f"{directory} is not a valid directory")
else:
if os.path.exists(directory) and os.path.isdir(directory):
target_path = directory
else:
print(f"{directory} is not a valid directory")
command_list = [func for func in dir(Commands) if callable(getattr(Commands, func)) and not func.startswith('__')]
os.system('cls')
while True:
command_has_kws = False
command = input(f'[{target_path}]{colorama.Fore.CYAN} @ {colorama.Fore.LIGHTBLUE_EX}').strip().split(' ')
print(colorama.Style.RESET_ALL, end='')
for i in range(len(command)):
command[i] = command[i].strip()
if command[i].startswith('-'):
command_has_kws = True
if command[0] in command_list:
try:
if not command_has_kws:
getattr(Commands, command[0])(*command[1:])
else:
# REMINDER: Type 'getattr(Commands, command[0]).__code__.co_varnames[:getattr(Commands, command[0]).__code__.co_argcount]' to get the parameters of a command
pass # TODO: Implement keywords
except TypeError:
print(f"{ERROR_COLOR}Too many or too little arguments were passed to '{command[0]}'{colorama.Style.RESET_ALL}")
else:
print(f"{ERROR_COLOR}'{command[0]}' is not recognized as a valid command! Do 'help' to see all valid commands{colorama.Style.RESET_ALL}\n")
Here's 2 things you should focus on:
target_path = f'C:\\Users\\{user}'
And:
@staticmethod
def cd(directory=''):
if directory == '':
print(target_path)
return
if directory[1] != ':':
if os.path.exists(target_path + directory) and os.path.isdir(target_path + directory):
target_path += directory
else:
print(f"{directory} is not a valid directory")
else:
if os.path.exists(directory) and os.path.isdir(directory):
target_path = directory
else:
print(f"{directory} is not a valid directory")
Also here's the error message:
Traceback (most recent call last):
File "C:\Users\[REDACTED]\Desktop\Crabby_CLI\main.py", line 132, in <module>
getattr(Commands, command[0])(*command[1:])
File "C:\Users\[REDACTED]\Desktop\Crabby_CLI\main.py", line 102, in cd
if os.path.exists(target_path + directory) and os.path.isdir(target_path + directory):
UnboundLocalError: local variable 'target_path' referenced before assignment
INFORMATION: Interpreter - Python 3.8 OS - Windows 10 Editor - PyCharm Community Edition
local variable 'target_path' referenced before assignment
this error suggests that you are trying to access target_path
in one of your functions before assigning any value and if my understanding is correct, you want to use the global target_path
, that you have set in top, within those functions.
If this is correct, then you need to tell your functions to use global variables.
Solution :
Within each function that uses the 'target_path' variable, in the beginning, put this line
def abc():
# add this line
global target_path
...
...
# now use `target_path` here