feat: Enhance German code execution and import logic

Introduced changes significantly improve how German code scripts are handled, ensuring a more robust and flexible execution environment. By wrapping the execution of transpiled code in a dedicated module, we facilitate a cleaner namespace management and mimic the natural Python script execution context more closely. This approach also allows for improved error handling and tracebacks that are more meaningful to the end-user.

The addition of "ausgenommen" as an alternative to "except" in the dictionary broadens the tool's understanding of German code, enhancing its flexibility and user-friendliness.

We've refined the module import mechanism to include a wider array of search paths, notably the script's directory and the current working directory, before falling back to the predefined wrappers directory. This enhancement makes the import process more intuitive and aligned with Python's standard behavior, ensuring that dependencies are resolved more reliably across diverse execution environments.

These improvements collectively bolster the tool's usability, making it more accommodating for users running and developing German-translated Python scripts.
This commit is contained in:
Kumi 2024-05-23 14:47:24 +02:00
parent 5ff8f3856b
commit 36f37c18b1
Signed by: kumi
GPG key ID: ECBCC9082395383F
3 changed files with 40 additions and 9 deletions

View file

@ -5,6 +5,7 @@ import tokenize
import pathlib import pathlib
import sys import sys
import traceback import traceback
import types
from argparse import ArgumentParser from argparse import ArgumentParser
@ -23,22 +24,33 @@ def main():
import_base(pathlib.Path(__file__).parent / "base") import_base(pathlib.Path(__file__).parent / "base")
if args.file: if args.file:
with open(args.file) as f: script_path = pathlib.Path(args.file).absolute()
german_code = f.read() script_dir = script_path.parent
# Read and transpile the German code
with open(script_path) as f:
german_code = f.read()
python_code = parse_german_code(german_code) python_code = parse_german_code(german_code)
# Compile the transpiled Python code
code_object = compile( code_object = compile(
python_code, python_code,
pathlib.Path(args.file).absolute(), str(script_path),
"exec", "exec",
dont_inherit=True, dont_inherit=True,
optimize=0, optimize=0,
) )
# Create a module for the script and add it to sys.modules
module_name = "__haupt__"
script_module = types.ModuleType(module_name)
script_module.__file__ = str(script_path)
sys.modules[module_name] = script_module
try: try:
exec(code_object, {"__file__": pathlib.Path(args.file).absolute()}) # Execute the compiled code within the module's namespace
except Ausnahme as e: # noqa: F821 exec(code_object, script_module.__dict__)
except Exception as e: # Replace Ausnahme with Exception for general error handling
# Extract traceback information, excluding frames related to the interpreter # Extract traceback information, excluding frames related to the interpreter
tb = e.__traceback__ tb = e.__traceback__
while tb is not None: while tb is not None:
@ -61,6 +73,5 @@ def main():
else: else:
interpreter() interpreter()
if __name__ == "__main__": if __name__ == "__main__":
sys.exit(main()) sys.exit(main())

View file

@ -34,6 +34,7 @@ dictionary = {
# Try / Except # Try / Except
"versuche": "try", "versuche": "try",
"außer": "except", "außer": "except",
"ausgenommen": "except",
"fange": "except", "fange": "except",
"schließlich": "finally", "schließlich": "finally",

View file

@ -3,7 +3,6 @@ import importlib.util
import importlib.machinery import importlib.machinery
import os import os
import tokenize import tokenize
import pathlib
import sys import sys
import builtins import builtins
@ -50,6 +49,26 @@ class DeuthonModuleFinder(importlib.abc.MetaPathFinder):
self.extension = extension self.extension = extension
def find_spec(self, fullname, path, target=None): def find_spec(self, fullname, path, target=None):
# Determine the search paths
search_paths = []
# Add the directory of the main script being executed
if "__haupt__" in sys.modules:
main_module = sys.modules["__haupt__"]
if hasattr(main_module, "__file__"):
script_dir = os.path.dirname(os.path.abspath(main_module.__file__))
search_paths.append(script_dir)
# Add any provided path
if path:
search_paths.extend(path)
# Add the current working directory
search_paths.append(os.getcwd())
# Add the wrappers directory
search_paths.append(self.wrappers_directory)
# Check inside the wrappers directory first # Check inside the wrappers directory first
deu_wrapper_path = os.path.join( deu_wrapper_path = os.path.join(
self.wrappers_directory, fullname + self.extension self.wrappers_directory, fullname + self.extension
@ -76,7 +95,7 @@ class DeuthonModuleFinder(importlib.abc.MetaPathFinder):
return spec return spec
# If it's not a wrapper, look for a .deu file # If it's not a wrapper, look for a .deu file
deu_path = self._find_deu_file(fullname, path) deu_path = self._find_deu_file(fullname, search_paths)
if deu_path: if deu_path:
loader = DeuthonSourceLoader(fullname, deu_path) loader = DeuthonSourceLoader(fullname, deu_path)
spec = importlib.util.spec_from_loader(fullname, loader, origin=deu_path) spec = importlib.util.spec_from_loader(fullname, loader, origin=deu_path)