# \[Python\] \[Stage #QP2\] Autocompletion works locally but fails tests

**URL:** <https://forum.codecrafters.io/t/python-stage-qp2-autocompletion-works-locally-but-fails-tests/6580>\
**Category:** Challenges\
**Tags:** challenge:shell\
**Created:** [March 12, 2025, 5:10pm UTC](https://forum.codecrafters.io/t/python-stage-qp2-autocompletion-works-locally-but-fails-tests/6580 "2025-03-12T17:10:23Z")\
**Posts on this page:** 6\
**Page:** 1

<div class="post-metadata">

**Author:** ![Jebach0](https://yyz1.discourse-cdn.com/flex003/user_avatar/forum.codecrafters.io/jebach0/32/5930_2.png) [@Jebach0](https://forum.codecrafters.io/u/Jebach0)\
**Post date:** [March 12, 2025, 5:10pm UTC](https://forum.codecrafters.io/t/python-stage-qp2-autocompletion-works-locally-but-fails-tests/6580/1 "2025-03-12T17:10:23Z")

</div>

```auto
import sys, shutil, subprocess, os, shlex, msvcrt

builtin_commands = {}

def command(func):
    builtin_commands[func. __name__.split("_")[1]] = func
    return func

@command
def shell_exit(args):
    exit(int(args[0]))

@command
def shell_echo(args):
    sys.stdout.write(" ".join(args) + "\n")

@command
def shell_type(args):
    if args[0] in builtin_commands:
        sys.stdout.write(f"{args[0]} is a shell builtin\n")
    elif path := shutil.which(args[0]):
        sys.stdout.write(f"{args[0]} is {path}\n")
    else:
        sys.stderr.write(f"{args[0]}: not found\n")

@command
def shell_pwd(args):
    sys.stdout.write(f"{os.getcwd()}\n")

@command
def shell_cd(args):
    path = args[0]
    if os.path.isdir(path) or path == "~":
        os.chdir(os.path.expanduser(path))
    else:
        sys.stderr.write(f"cd: {path}: No such file or directory\n")

def get_completion(input):
    return list(filter(lambda cmnd: cmnd.startswith(input), builtin_commands))

def write_and_flush(data):
    sys.stdout.write(data)
    sys.stdout.flush()

def get_input():
    user_input = ""
    print("$ ", end="", flush=True)
    
    while True:
        char = msvcrt.getwch()
        if char == "\r":
            print()
            return user_input
        elif char == "\b":
            if len(user_input) > 0:
                user_input = user_input[:-1]
                print("\b \b", end="", flush=True)
        elif char == "\t":  
            completions = get_completion(user_input.strip())
            if completions:
                completion = completions[0]
                user_input = completion + " "
                
                sys.stdout.write(f"\r$ {user_input}")
                sys.stdout.flush()
        else:  
            user_input += char
            print(char, end="", flush=True)
    
    sys.stdout.write("\n")
    return user_input

def redirect(args, command, operator):
    if len(args) < 3:
        return

    redirect_index = args.index(operator)
    cmd_args = args[:redirect_index]
    file_name = args[redirect_index + 1]

    method = "w" if operator in [">", "1>", "2>"] else "a"

    if command in builtin_commands:
        try:
            with open(file_name, method) as f:
                old_output = sys.stdout if operator in [">", "1>",">>","1>>"] else sys.stderr
                if operator in [">", "1>",">>","1>>"]:
                    sys.stdout = f
                elif operator in ["2>", "2>>"]:
                    sys.stderr = f

                builtin_commands[command](cmd_args)

        except Exception as e:
            sys.stdout.write(f"Error executing command {command}: {e}\n")
        finally:
            if operator in [">", "1>",">>","1>>"]:
                sys.stdout = old_output
            elif operator in ["2>", "2>>"]:
                sys.stderr = old_output
    else:
        executable = shutil.which(command)
        if executable:
            with open(file_name, method) as f:
                if operator in [">", "1>",">>","1>>"]:
                    subprocess.run([command] + cmd_args, stdout=f)
                else:
                    subprocess.run([command] + cmd_args, stderr=f)
        else:
            sys.stdout.write(f"{command}: command not found\n")

def main():
    while True:
        user_input = get_input()
        cmd, *args = shlex.split(user_input)

        redirect_operator = next((operator for operator in [">","1>","2>",">>", "1>>", "2>>"] if operator in args), None)
        

        if redirect_operator:
            redirect(args, cmd, redirect_operator)
        else:       
            if cmd in builtin_commands:
                builtin_commands[cmd](args)
            elif executable := shutil.which(cmd):
                subprocess.run([cmd] + args)
            else:
                sys.stdout.write(f"{cmd}: command not found\n")

if __name__ == " __main__":
    main()

```

---

<div class="post-metadata">

**Author:** ![andy1li](https://yyz1.discourse-cdn.com/flex003/user_avatar/forum.codecrafters.io/andy1li/32/10_2.png) [@andy1li](https://forum.codecrafters.io/u/andy1li)\
**Post date:** [March 13, 2025, 3:54am UTC](https://forum.codecrafters.io/t/python-stage-qp2-autocompletion-works-locally-but-fails-tests/6580/2 "2025-03-13T03:54:00Z")

</div>

Hey @Jebach0, what errors are you seeing?

---

<div class="post-metadata">

**Author:** ![Jebach0](https://yyz1.discourse-cdn.com/flex003/user_avatar/forum.codecrafters.io/jebach0/32/5930_2.png) [@Jebach0](https://forum.codecrafters.io/u/Jebach0)\
**Post date:** [March 13, 2025, 1:45pm UTC](https://forum.codecrafters.io/t/python-stage-qp2-autocompletion-works-locally-but-fails-tests/6580/3 "2025-03-13T13:45:22Z")

</div>

@andy1li This is the output I’m getting

remote: [tester::#QP2] Running tests for Stage #QP2 (Autocompletion - Builtin completion)  
remote: [tester::#QP2] Running ./your\_program.sh  
remote: [tester::#QP2] ✓ Received prompt ($ )  
remote: [tester::#QP2] Typed “ech”  
remote: [tester::#QP2] ✓ Prompt line matches “$ ech”  
remote: [tester::#QP2] Pressed “” (expecting autocomplete to “echo”)  
remote: [your-program] $ ech  
remote: [tester::#QP2] Output does not match expected value.  
remote: [tester::#QP2] Expected: "$ echo "  
remote: [tester::#QP2] Received: "$ ech "  
remote: [tester::#QP2] Assertion failed.  
remote: [tester::#QP2] Test failed (try setting ‘debug: true’ in your codecrafters.yml to see more details)  
remote:  
remote: Try our CLI to run tests faster without Git: [How do I install the CLI? - CodeCrafters](https://codecrafters.io/cli)  
remote:  
remote: View our article on debugging test failures: [How do I debug test failures? - CodeCrafters](https://codecrafters.io/debug)  
remote:  
To [https://git.codecrafters.io/5ac8d4f248023317](https://git.codecrafters.io/5ac8d4f248023317)

---

<div class="post-metadata">

**Author:** ![andy1li](https://yyz1.discourse-cdn.com/flex003/user_avatar/forum.codecrafters.io/andy1li/32/10_2.png) [@andy1li](https://forum.codecrafters.io/u/andy1li)\
**Post date:** [March 20, 2025, 3:56pm UTC](https://forum.codecrafters.io/t/python-stage-qp2-autocompletion-works-locally-but-fails-tests/6580/5 "2025-03-20T15:56:18Z")

</div>

@Jebach0 Nice use of the command decorator! 👍

The default setup does not allow reading one char at a time from stdin:

 ![image](https://canada1.discourse-cdn.com/flex003/uploads/codecrafters/original/2X/2/2857338c29d8363ee5efca6c41b0ceedcceb3e45.png)

 ![image](https://canada1.discourse-cdn.com/flex003/uploads/codecrafters/original/2X/c/ccc20b7954480e94ce0e5de179619359eafa0215.png)

Input is currently buffered until **enter** is pressed. To handle character-by-character input, you may want to research **raw mode** or use **readline**.

Let me know if you’d like further clarification!

---

<div class="post-metadata">

**Author:** ![andy1li](https://yyz1.discourse-cdn.com/flex003/user_avatar/forum.codecrafters.io/andy1li/32/10_2.png) [@andy1li](https://forum.codecrafters.io/u/andy1li)\
**Post date:** [March 30, 2025, 4:42pm UTC](https://forum.codecrafters.io/t/python-stage-qp2-autocompletion-works-locally-but-fails-tests/6580/7 "2025-03-30T16:42:41Z")

</div>

Closing this thread due to inactivity. If you still need assistance, feel free to reopen or start a new discussion!

---

<div class="post-metadata">

**Author:** ![system](https://canada1.discourse-cdn.com/flex003/uploads/codecrafters/original/3X/7/0/700657133935c15703e22c7c8870394f6e6dc27d.svg) [@system](https://forum.codecrafters.io/u/system)\
**Post date:** [April 4, 2025, 4:43pm UTC](https://forum.codecrafters.io/t/python-stage-qp2-autocompletion-works-locally-but-fails-tests/6580/8 "2025-04-04T16:43:04Z")

</div>

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