Skip to content

Monic Framework is a powerful expression evaluation and code execution framework that provides a safe and flexible way to parse and interpret Python-style code.

License

Notifications You must be signed in to change notification settings

cognica-io/monic-framework

Repository files navigation

Monic Framework

Code coverage Package version Supported Python versions PyPI - Downloads PyPI - License

Monic Framework is a powerful expression evaluation and code execution framework that provides a safe and flexible way to parse and interpret Python-style code. It offers a robust expression parser and interpreter designed for dynamic code evaluation, scripting, and embedded programming scenarios.

Key Features

  • Python-style syntax support
  • Secure code execution environment
  • Expression parsing and interpretation
  • Function definition and call support
  • Built-in type checking and validation
  • Seamless integration with existing Python projects
  • CPU profiling support

Supported Language Features

Core Python Features

  • Variables and basic data types (int, float, str, bool, etc.)
  • Control flow statements (if/else, for, while, break, continue)
  • Functions with full parameter support:
    • Positional and keyword arguments
    • Default values
    • Variable arguments (*args)
    • Keyword arguments (**kwargs)
    • Keyword-only arguments
  • Lambda expressions
  • List, set, and dictionary comprehensions
  • Context managers (with statements)
  • Exception handling (try/except/finally)
  • Classes and object-oriented programming
  • Pattern matching (match/case statements)

Expression Support

  • Arithmetic operations (+, -, *, /, //, %, **)
  • Comparison operations (==, !=, <, >, <=, >=)
  • Logical operations (and, or, not)
  • Bitwise operations (&, |, ^, <<, >>)
  • Assignment operations (=, +=, -=, *=, etc.)
  • Attribute access (obj.attr)
  • Subscript operations (obj[key])
  • Function and method calls
  • String formatting (f-strings)
  • Tuple and list unpacking
  • Named expressions (walrus operator :=)

Built-in Functions and Types

  • Essential built-ins (print, len, range, etc.)
  • Type conversion functions (int, float, str, bool)
  • Collection operations (min, max, sum, sorted)
  • Iteration helpers (enumerate, zip, filter, map)
  • Type checking (isinstance, issubclass)

Security Features

  • Sandboxed execution environment
  • Restricted access to system resources
  • Prevention of malicious code execution
  • Execution timeout protection:
    • Configurable maximum execution time
    • Automatic termination of long-running code
    • Protection against infinite loops
    • Time-based resource control
  • Forbidden operations disallowed:
    • File system operations
    • System command execution
    • Module imports
    • Access to sensitive attributes directly or indirectly
    • Access to forbidden modules directly or indirectly
    • Dangerous built-in functions

Installation

Basic Installation

pip install -U monic-framework

Or with extra dependencies such as pyarrow, numpy, pandas, and polars:

pip install -U monic-framework[extra]

Development Installation

pip install -e .[dev]

Or with extra dependencies such as pyarrow, numpy, pandas, and polars:

pip install -e .[dev,extra]

Quick Start

Basic Usage

from monic.expressions import ExpressionsParser, ExpressionsInterpreter


# Initialize parser and interpreter
parser = ExpressionsParser()
interpreter = ExpressionsInterpreter()

# Define code to execute
code = """
# Variable assignment
x = 10
y = 20

# Conditional statement
if x < y:
    result = "y is greater"
else:
    result = "x is greater"

# Return result
result
"""

# Parse code and execute it
tree = parser.parse(code)
result = interpreter.execute(tree)
print(result)  # Output: "y is greater"

Function Definition and Calls

from monic.expressions import ExpressionsParser, ExpressionsInterpreter


# Initialize parser and interpreter
parser = ExpressionsParser()
interpreter = ExpressionsInterpreter()

# Define code to execute
code = """
def calculate_sum(a: int, b: int) -> int:
    return a + b

def calculate_average(numbers: list[int]) -> float:
    total = 0
    for num in numbers:
        total += num
    return total / len(numbers)

# Using functions
sum_result = calculate_sum(10, 20)
avg_result = calculate_average([1, 2, 3, 4, 5])

[sum_result, avg_result]
"""

# Parse code and execute it
tree = parser.parse(code)
result = interpreter.execute(tree)
print(result)  # Output: [30, 3.0]

Binding Python Objects

from monic.expressions import (
    ExpressionsParser,
    ExpressionsInterpreter,
    monic_bind,
)


# Define functions and bind them to the interpreter
@monic_bind
def calculate_sum(x: int, y: int) -> int:
    return x + y


@monic_bind
def calculate_average(numbers: list[int]) -> float:
    total = 0
    for num in numbers:
        total += num
    return total / len(numbers)


# Initialize parser and interpreter
parser = ExpressionsParser()
interpreter = ExpressionsInterpreter()

# Define code to execute
code = """
# Using bound functions
sum_result = calculate_sum(10, 20)
avg_result = calculate_average([1, 2, 3, 4, 5])

[sum_result, avg_result]
"""

# Parse code and execute it
tree = parser.parse(code)
result = interpreter.execute(tree)
print(result)  # Output: [30, 3.0]

Timeout Control

from monic.expressions import ExpressionsParser, ExpressionsContext, ExpressionsInterpreter


# Initialize parser
parser = ExpressionsParser()
# Initialize with timeout context
context = ExpressionsContext(timeout=5.0)  # Set 5 seconds timeout
# Initialize interpreter with context
interpreter = ExpressionsInterpreter(context=context)

# This will be terminated after 5 seconds
code = """
while True:
    pass  # Infinite loop
"""

try:
    tree = parser.parse(code)
    interpreter.execute(tree)
except TimeoutError:
    print("Code execution timed out")  # Output: Code execution timed out

CPU Profiling

from monic.expressions import ExpressionsParser, ExpressionsContext, ExpressionsInterpreter


# Initialize parser
parser = ExpressionsParser()
# Initialize with profiling context
context = ExpressionsContext(enable_cpu_profiling=True)
# Initialize interpreter with context
interpreter = ExpressionsInterpreter(context=context)
# Verify that the CPU profiler is initialized
assert interpreter.cpu_profiler is not None

# Define the code to profile
code = """
def binary_search(arr: list[int], target: int) -> int:
    if not arr:
        return -1

    left = 0
    right = len(arr) - 1

    while left <= right:
        mid = (left + right) // 2

        if arr[mid] == target:
            return mid
        elif arr[mid] < target:
            left = mid + 1
        else:
            right = mid - 1

    return -1

test_arr = [1, 3, 5, 7, 9, 11, 13, 15]

print(f"Array: {test_arr}")
print(f"Search for 7: {binary_search(test_arr, 7)}")  # Should return 3
print(f"Search for 15: {binary_search(test_arr, 15)}")  # Should return 7
print(f"Search for 10: {binary_search(test_arr, 10)}")  # Should return -1
print(f"Search for 1: {binary_search(test_arr, 1)}")  # Should return 0
"""

# Parse code and execute it
tree = parser.parse(code)
interpreter.execute(tree)

# Get report with code snippets
report = interpreter.cpu_profiler.get_report_as_string(code=code)
print(report)

License

This project is licensed under the terms specified in the LICENSE file.

Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

Issues and Support

For bug reports or feature requests, please submit them through GitHub Issues.

About

Monic Framework is a powerful expression evaluation and code execution framework that provides a safe and flexible way to parse and interpret Python-style code.

Topics

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages