import time
from queue import Queue
from threading import Thread
from tkinter import ttk, Tk, StringVar, W, EW, SUNKEN
from decimal import Decimal, getcontext, Overflow
import ast
import operator as op

# Safe evaluation setup
allowed_operators = {
    ast.Add: op.add, ast.Sub: op.sub, ast.Mult: op.mul,
    ast.Div: op.truediv, ast.Pow: op.pow, ast.BitXor: op.xor,
    ast.USub: op.neg
}

def safe_eval(expr):
    """
    Safely evaluate an arithmetic expression using AST.
    """
    def eval_(node):
        if isinstance(node, ast.Num):  # <number>
            return Decimal(node.n)
        elif isinstance(node, ast.BinOp):  # <left> <operator> <right>
            return allowed_operators[type(node.op)](eval_(node.left), eval_(node.right))
        elif isinstance(node, ast.UnaryOp):  # <operator> <operand> e.g., -1
            return allowed_operators[type(node.op)](eval_(node.operand))
        else:
            raise TypeError(node)
    
    return eval_(ast.parse(expr, mode='eval').body)

def format_scientific(number: Decimal, digit_limit: int) -> str:
    """Format the number in scientific notation if it exceeds digit_limit."""
    try:
        if len(str(number).replace('.', '').replace('-', '')) > digit_limit:
            return "{:.{}e}".format(number, digit_limit - 1)
        return str(number)
    except Overflow:
        # Handle numbers that are too large
        return number.to_eng_string()

class ExpressionParser:
    """Class to parse and evaluate mathematical expressions safely."""
    
    def __init__(self) -> None:
        self.precision = 10000  # Set high precision for large numbers
        
    def evaluate(self, expression: str, digit_limit: int) -> str:
        """Parse an expression and evaluate the result safely."""
        getcontext().prec = self.precision
        try:
            result = safe_eval(expression)
            return format_scientific(result, digit_limit)
        except Exception as e:
            raise ValueError(f"Invalid expression: {e}") from e

class GuiUpdater:
    """Class to update GUI with results and status."""
    
    def __init__(self, root: Tk, result_var: StringVar, status_var: StringVar, entry_var: StringVar, digit_limit_var: StringVar) -> None:
        self.root = root
        self.result_var = result_var
        self.status_var = status_var
        self.entry_var = entry_var
        self.digit_limit_var = digit_limit_var
        self.queue: "Queue[Tuple[str, float]]" = Queue()
        
        self.start()
        
    def start(self) -> None:
        """Start background thread to process result queue."""
        self.worker = Thread(target=self.process_queue, daemon=True)
        self.worker.start()
        
    def process_queue(self) -> None:
        """Get results from queue and update GUI."""
        while True:
            result, duration = self.queue.get()
            
            self.update_result(result)
            self.update_status(f"Computation Time: {duration:.2f} sec")
            
            self.root.update_idletasks()
        
    def update_result(self, result: str) -> None:
        """Update result label with calculation result."""
        self.result_var.set(f"Result: {result}")
        
    def update_status(self, status: str) -> None:
        """Update status bar with latest status."""
        self.status_var.set(status)

class LargeNumberCalculatorApp:
    """Main application class to coordinate between GUI and calculation."""
    
    def __init__(self, root: Tk) -> None:
        self.root = root
        self.parser = ExpressionParser()
        self.result_var = StringVar()
        self.status_var = StringVar()
        self.entry_var = StringVar()
        self.digit_limit_var = StringVar(value="10")  # Default digit limit
        self.gui = self.build_gui()
        
    def build_gui(self) -> GuiUpdater:
        """Build GUI elements."""
        entry = ttk.Entry(self.root, textvariable=self.entry_var)
        entry.grid(row=0, column=1, sticky=EW)
        
        calculate_button = ttk.Button(self.root, text="Calculate", command=self.calculate)
        calculate_button.grid(row=1, column=1, sticky=W)
        
        clear_button = ttk.Button(self.root, text="Clear", command=lambda: self.entry_var.set(""))
        clear_button.grid(row=1, column=2, sticky=W)
        
        digit_limit_label = ttk.Label(self.root, text="Digit Limit:")
        digit_limit_label.grid(row=0, column=2)
        digit_limit_entry = ttk.Entry(self.root, textvariable=self.digit_limit_var)
        digit_limit_entry.grid(row=0, column=3)
        
        result_label = ttk.Label(self.root, textvariable=self.result_var)
        result_label.grid(row=2, column=1, sticky=W)
        
        status_label = ttk.Label(self.root, textvariable=self.status_var, relief=SUNKEN, anchor=W)
        status_label.grid(row=3, column=0, columnspan=4, sticky=EW)
        
        return GuiUpdater(self.root, self.result_var, self.status_var, self.entry_var, self.digit_limit_var)
        
    def calculate(self) -> None:
        """Handler for calculate button click, modified for asynchronous execution."""
        expression = self.entry_var.get()
        digit_limit = int(self.digit_limit_var.get())
        
        def async_calculate():
            start = time.perf_counter()
            
            try:
                result = self.parser.evaluate(expression, digit_limit)
            except Exception as e:
                result = f"Error: {e}"
                
            duration = time.perf_counter() - start
            
            # Send result to GUI update handler in the main thread
            self.root.after(0, lambda: self.gui.queue.put((result, duration)))
        
        # Run calculation in a separate thread
        Thread(target=async_calculate, daemon=True).start()
        
if __name__ == "__main__":
    root = Tk()
    app = LargeNumberCalculatorApp(root)
    root.mainloop()

Write a 2.0 of this. You have full freedom to change anything here, including the framework.