Import readline not supported in Python 3.14

I’m stuck on Stage #RH7 or Shell with Python

I’ve tried installing the readline package using pip install readline. ChatGPT recommended using pyreadline3, tried that as well.

Althought VSCode is showing me an error, I guess it is working relatively fine in testing. Please look into it.

Here are my logs:

remote: [compile] Moved ./.codecrafters/run.sh → ./your_program.sh
remote: [compile] Compilation successful.
remote:
remote: [tester::#RH7] Running tests for Stage #RH7 (History - Up-arrow navigation)
remote: [tester::#RH7] Running ./your_program.sh
remote: [your-program] $ echo banana mango
remote: [your-program] banana mango
remote: [tester::#RH7] ✓ Command executed successfully
remote: [your-program] $ echo mango apple
remote: [your-program] mango apple
remote: [tester::#RH7] ✓ Command executed successfully
remote: [your-program] $ invalid_grape_command
remote: [your-program] invalid_grape_command: command not found
remote: [tester::#RH7] ✓ Received command not found message
remote: [your-program] $ echo orange apple
remote: [your-program] orange apple
remote: [tester::#RH7] ✓ Command executed successfully
remote: [tester::#RH7] Pressed “” (expecting to recall “echo orange apple”)
remote: [tester::#RH7] ✓ Prompt line matches “echo orange apple”
remote: [tester::#RH7] Pressed “” (expecting to recall “invalid_grape_command”)
remote: [your-program] $ echo orange apple
remote: [tester::#RH7] ^ Line does not match expected value.
remote: [tester::#RH7] Expected: “$ invalid_grape_command”
remote: [tester::#RH7] Received: “$ echo orange apple”
remote: [tester::#RH7] Assertion failed.
remote: [tester::#RH7] Test failed

And here’s a snippet of my code:

import sys, os
import readline

SHELL_BUILTIN = ["echo", "exit", "type", "history"]
PATH = os.getenv("PATH", "")
paths = PATH.split(":")
HISTORY = []

def find_exec(cmd):
    for path in paths:
        full_path = f"{path}/{cmd}"
        try:
            with open(full_path):
                if os.access(full_path, os.X_OK):
                    return full_path
        except FileNotFoundError:
            continue
    return None

def main():
    sys.stdout.write("$ ")
    command = input()
    HISTORY.append(command)
    readline.add_history(command)
    if command == "exit":
        sys.exit()
    elif command.split(" ")[0] == "echo":
        print(command[5:])
    elif command[:7] == "history":
        if len(command.split(" "))>1:
            count = int(command.split(" ")[1])
            for i in range(len(HISTORY)-count, len(HISTORY)):
                print(f"{i+1} {HISTORY[i]}")
        else:
            for index, cmd in enumerate(HISTORY):
                print(f"{index+1} {cmd}")
    elif command.split(" ")[0] == "type":
        if command[5:] in SHELL_BUILTIN:
            print(f"{command[5:]} is a shell builtin")
        elif find_exec(command[5:]):
            print(f"{command[5:]} is {find_exec(command[5:])}")
        else:
            print(f"{command[5:]}: not found")
    elif find_exec(command.split(" ")[0]):
        os.system(command)
    else:
        print(f"{command}: command not found")

if __name__ == "__main__":
    while True:
        main()

Hey @ABarpanda, could you try the GNU readline module from the standard library instead?

Ok, I asked AI to write the code for me
This one works -

import sys, os
import readline

SHELL_BUILTIN = ["echo", "exit", "type", "history"]
PATH = os.getenv("PATH", "")
paths = PATH.split(":")
HISTORY = []

def find_exec(cmd):
    for path in paths:
        full_path = f"{path}/{cmd}"
        try:
            if os.access(full_path, os.X_OK):
                return full_path
        except FileNotFoundError:
            continue
    return None

def sync_readline_history():
    """Sync readline history with our HISTORY list"""
    readline.clear_history()
    for cmd in HISTORY:
        readline.add_history(cmd)

def main():
    global HISTORY
    
    # SYNC readline history BEFORE input() so arrows work correctly
    sync_readline_history()
    
    try:
        command = input("$ ").strip()
    except EOFError:
        sys.exit()
    
    # Add to OUR history
    HISTORY.append(command)
    
    if command == "exit":
        sys.exit()
    elif command.startswith("echo "):
        print(command[5:])
    elif command.startswith("history"):
        parts = command.split(" ")
        if len(parts) > 1:
            try:
                count = int(parts[1])
                start = max(0, len(HISTORY) - count)
                for i in range(start, len(HISTORY)):
                    print(f"{i+1} {HISTORY[i]}")
            except ValueError:
                print("history: invalid count")
        else:
            for index, cmd in enumerate(HISTORY):
                print(f"{index+1} {cmd}")
    elif command.startswith("type "):
        cmd_name = command[5:].strip()
        if cmd_name in SHELL_BUILTIN:
            print(f"{cmd_name} is a shell builtin")
        elif find_exec(cmd_name):
            print(f"{cmd_name} is {find_exec(cmd_name)}")
        else:
            print(f"{cmd_name}: not found")
    elif find_exec(command.split(" ")[0]):
        os.system(command)
    else:
        print(f"{command}: command not found")

if __name__ == "__main__":
    try:
        while True:
            main()
    finally:
        # Save history
        histfile = os.path.expanduser("~/.myshell_history")
        readline.write_history_file(histfile)

1 Like

This topic was automatically closed 5 days after the last reply. New replies are no longer allowed.