Source code for python_project_template_AS.operations

"""Operation container and a few example math operations.

The :class:`Operation` is a tiny callable wrapper that validates arity and
delegates to the underlying function. A small set of convenience
instances (ADD, SUB, MUL, DIV, NEG, SQR) are provided for tests/examples.
"""

from dataclasses import dataclass
from typing import Callable, Any

from .exceptions import OperationError


[docs] @dataclass class Operation: """Named callable with arity check. Attributes: name (str): Operation name. func (Callable): Operation function. arity (int): Expected argument count. """ name: str func: Callable[..., Any] arity: int = 1 def __call__(self, *args): """Call operation, checking argument count. Args: *args: Arguments for the operation. Raises: OperationError: If argument count is wrong. """ if len(args) != self.arity: raise OperationError( f"Operation '{self.name}' expects {self.arity} arguments, got {len(args)}" ) return self.func(*args)
# --- Example operations -------------------------------------------------
[docs] def add(a, b): """Return the sum of two numbers.""" return a + b
[docs] def sub(a, b): """Return the difference of two numbers.""" return a - b
[docs] def mul(a, b): """Return the product of two numbers.""" return a * b
[docs] def safe_div(a, b): """Divide a by b, raising :class:`OperationError` on zero division.""" try: return a / b except ZeroDivisionError as e: raise OperationError("Division by zero") from e
[docs] def neg(a): """Return the numeric negation of a value.""" return -a
[docs] def square(a): """Return the square of a value.""" return a * a
# Convenience instances ADD = Operation("add", add, arity=2) SUB = Operation("sub", sub, arity=2) MUL = Operation("mul", mul, arity=2) DIV = Operation("div", safe_div, arity=2) NEG = Operation("neg", neg, arity=1) SQR = Operation("sqr", square, arity=1)