Override Built-in Function Python

Hi,

My program needs to override a built-in function, and my current solution doesn’t seem to work with Python 3. I found this gist on GitHub, but it was written in Python 2, and __bulitin__ does seem to exist anymore. Is there a way to do this with Python 3?

My current solution:

import __builtin__ # This doesn't seem to exist anymore


def file_exec(path):
    with open(path, "r") as f:
        exec(f.read())


__builtin__.exec = file_exec

Any help is greatly appreciated!

Update, it looks like __builtin__ for Python3 is builtins, but after replacing everything correctly, using the overridden function gives the error, TypeError: file_exec() takes 1 positional argument but 2 were given, but I only supplied it with one argument.

1 Like

Ah. I suspect you’re getting passed self then. Just add an unused argument as the first parameter. Or maybe the second one is unused, but that’s not typical.

1 Like

Seems to fix that, but now I get TypeError: expected str, bytes or os.PathLike object, not dict, though I’m not passing anything different into the with open(), the location where the error is occuring.

Odd. Try adding a print statement into it to print both of its parameters for troubleshooting so we can see what it’s doing.

1 Like

So currently, this is my code. Is this what you meant?

Edit: Nevermind I misunderstood

import builtins


def file_exec(randomParameter, path):
    print(f"{randomParameter} {path}")
    with open(path, "r") as f:
        exec(f.read())


builtins.exec = file_exec
exec("randomArg", "file.py")

No, I meant something like this:

import builtins


def file_exec(unused, file):
    print(f"""1. {unused}
2. {file}""")
    with open(path, "r") as f:
        exec(f.read())


builtins.exec = file_exec
exec("file.py")

Assuming your code only passes a file name to the call, I think this should print whatever python is doing.

Also, that’s going to cause a recursive call I think, probably do this:

bkpExec = exec
# stuff goes here
        bkpExex(f.read())
# Other stuff.
2 Likes

Ok, before we continue, I should probably provide a bit of background information I realized I should have provided earlier. Currently, the file_exec command is being imported from another file, and so is a function for reading files, but I’d assume everything would work the same. I’ll link the full error below.

Full Error
Traceback (most recent call last):
  File "src/boot.py", line 22, in <module>
    exec("a", "install.py")
  File "/home/runner/pyos3/src/func/util.py", line 5, in file_exec
    exec(read_file(path))
  File "/home/runner/pyos3/src/func/file.py", line 7, in read_file
    with open(path, "r") as file:
FileNotFoundError: [Errno 2] No such file or directory: 'install.py'
Failed calling sys.__interactivehook__
Traceback (most recent call last):
  File "/nix/store/hd4cc9rh83j291r5539hkf6qd8lgiikb-python3-3.10.8/lib/python3.10/site.py", line 447, in register_readline
    import rlcompleter
  File "/home/runner/pyos3/src/func/util.py", line 5, in file_exec
    exec(read_file(path))
  File "/home/runner/pyos3/src/func/file.py", line 7, in read_file
    with open(path, "r") as file:
TypeError: expected str, bytes or os.PathLike object, not dict

Can you link your Repl?

2 Likes

Will do, its a bit of a mess currently so let me know if anything is confusing.

https://replit.com/@bobbypac/pyos3

Hm. Try flipping the file name and argument parameters.

1 Like

No luck, it still results in the same error.

1 Like

Huh. Try the printer mentioned earlier:

Attempted edit to make it work in your code’s context:

def file_exec(randomArg, path):
    print(f"""1. {randomArg}
2. {path}""")
    exec(read_file(path))

Well, I think I know why its flaring up now,

Output:

1. <code object <module> at 0x7f1ec60dd6e0, file "/nix/store/hd4cc9rh83j291r5539hkf6qd8lgiikb-python3-3.10.8/lib/python3.10/rlcompleter.py", line 1>

2. {'__name__': 'rlcompleter', '__doc__': None, '__package__': '', '__loader__': <_frozen_importlib_external.SourceFileLoader object at 0x7f1ec60a2b90>, '__spec__': ModuleSpec(name='rlcompleter', loader=<_frozen_importlib_external.SourceFileLoader object at 0x7f1ec60a2b90>, origin='/nix/store/hd4cc9rh83j291r5539hkf6qd8lgiikb-python3-3.10.8/lib/python3.10/rlcompleter.py'), '__file__': '/nix/store/hd4cc9rh83j291r5539hkf6qd8lgiikb-python3-3.10.8/lib/python3.10/rlcompleter.py', '__cached__': '/nix/store/hd4cc9rh83j291r5539hkf6qd8lgiikb-python3-3.10.8/lib/python3.10/__pycache__/rlcompleter.cpython-310.pyc'}

Adjusted it a bit for readability

That’s um. Certainly not what we were trying to pass, lol. Where was it called?

Called it in src/boot.py, where I overrid Python’s default exec().

Hm. Off chance, but try changing util.py to:

from func.file import read_file
import builtins

backupExec = builtins.exec

def file_exec(randomArg, path):
    print(f"""1. {randomArg}
2. {path}""")
    backupExec(read_file(path))

Still no luck, this might be a bit far-fetched. Honestly, I’m not really sure why I even have to override it in the first place.

Instead of overriding the builtin, try just overriding exec itself?

Example:

builtins.exec = file_exec
# To
exec = file_exec
1 Like

It seems to want a dictionary now.

Traceback (most recent call last):
  File "src/boot.py", line 20, in <module>
    exec("a", "install.py")
TypeError: exec() globals must be a dict, not str