Interactive and asynchronous stdin console written in pure Python and asyncio with extension support Can be used together with any Python project that uses asyncio, especially servers and web-based apps. Only POSIX operating systems are supported, such as Linux, *BSD, Solaris etc. Windows support isn't coming soon.
Simple quickstart that will bring on the working command prompt in asyncio environment:
import asyncio
from admin_console import AdminCommandExecutor, basic_command_set, colors
async def main():
console = AdminCommandExecutor(use_config=False) # do not load config.json in the current directory
basic_command_set(console) # exit, extlist, extload, extunload etc.
# Custom prompt formatting
console.promptheader = "Tutorial! "
console.promptarrow = "->"
console.prompt_format['bold'] = True
console.prompt_format['fgcolor'] = colors.GREEN
await console.load_extensions() # will create an "extensions/" in the working directory
await console.prompt_loop() # blocks until > exit is invoked
if __name__ == "__main__":
asyncio.run(main())
# Note: create extdep.txt in the extensions folder to sequentally load modules
# Tutorial! ->
Example of how to handle command dispatching and how to cancel some commands
from admin_console import AdminCommand
# Add handler
async def handler(cmd: AdminCommand, executor: AdminCommandExecutor, *args):
executor.print("Command executed! If this command's name contains bad, it is cancelled!")
if 'bad' in cmd.name:
return False # cancel!
console.cmdexec_event.add_handler(handler)
# Wait for the event
await console.cmdexec_event.wait_for_successful()
console.print("Some command is executed!")
# Wait until an event happens and then determine if this event passes
async with console.cmdexec_event.wait_and_handle() as handle:
# success is True if this event is not cancelled, False otherwise
# args is the list and kwargs is the dictionary of the arguments of an event
success, args, kwargs = handle()
if not success:
# event is already cancelled
pass
elif args[0] = "bad" and kwargs["user"] = "hacker":
# cancel an event
handle(False)
# Trigger an event and decide if it happened correctly
custom_event = console.events['some_custom_event'] # collections.defaultdict creates a new instance if there is no such an element
async with custom_event.emit_and_handle("good", "argument", 123, before=True) as handle:
# putting before=True to evaluate the code before handlers
handle(True) # make this event uncancellable, next time handle(False) call won't have an effect
Extensions are importable Python script files (name.py) and they should be put in the extensions/
directory of the script.
Each extension script should have async def extension_init(self)
and async def extension_cleanup(self)
async function definitions,
where self
is an instance of AdminCommandExtension
. Example:
from admin_console import AdminCommandExtension
async def extension_init(self: AdminCommandExtension):
self.msg("Welcome here! Registering commands...")
async def my_command(cmd: AdminCommandExecutor, arg1: str, arg2: int, arg3: bool, arg4: float, arg5: str):
# do it yourself
pass
async def my_command_tab(cmd: AdminCommandExecutor, *args, argl: str):
_len = len(args)
if argl:
_len += 1
if _len == 0:
# arg1 is being tabbed, which is a single word
return "foo", "bar", "lore", "bug"
elif _len == 1:
# arg2 is being tabbed, which is int
# do not tabcomplete an integer...
pass
elif _len == 2:
# it is possible to tabcomplete a boolean, which is just yes or no
return "yes", "no"
self.add_command(my_command, 'my-command', ((str, 'some word'), (int, 'your amount'), (bool, 'yes or no?'), (float, 'write precise PI here'), (None, 'long line...')), my_command_tab)
# do LITERALLY anything at the extension load time, but be careful: it stops the other extensions from loading while this function is running
async def extension_cleanup(self: AdminCommandExtension):
self.msg("Goodbye...")
Make a file at the extensions directory with the contents above. The extension should be .py
, otherwise the script won't be imported.
To tell the extension loader to load scripts in the specified order, make extdep.txt
in the extensions/
directory
and fill the file names (without .py) on each line.
Simple rendered reference is here: https://nobwow.github.io/admin_console.html
pip install -U git+https://github.com/NobWow/admin-console-python.git