Small library to dynamically create python functions.
—
Function compilation utilities for masking implementation details from debuggers while preserving source code access for development purposes. These utilities provide a way to create "compiled" versions of functions that hide their implementation from debugging tools while maintaining functionality.
from typing import Union, Callable, IterableDecorator that compiles functions to mask their implementation from debuggers while preserving source code access.
def compile_fun(recurse: Union[bool, Callable] = True,
except_names: Iterable[str] = ()) -> Union[Callable, Callable[[Callable], Callable]]:
"""
Decorator to compile functions for debugging convenience.
Compiles any existing function so that users can't debug through it,
which can be handy to mask some code from users for convenience.
The source code is preserved in the __source__ attribute.
Parameters:
- recurse: Union[bool, Callable], default True
If True, recursively compile referenced functions in closure.
If Callable, apply compilation immediately (no-args decorator usage).
- except_names: Iterable[str], default ()
Function names to exclude from recursive compilation
Returns:
Union[Callable, Callable[[Callable], Callable]]:
- If called with parentheses: returns decorator function
- If called without parentheses: returns compiled function directly
Raises:
UnsupportedForCompilation: If target is not a function
UndefinedSymbolError: If function references undefined symbols
SourceUnavailable: If function source code cannot be retrieved
Note:
- Compilation does not improve performance (per Python design)
- Primary use is hiding implementation details during debugging
- Source code remains available via __source__ attribute
- Recursively compiles closure functions by default
"""class UndefinedSymbolError(NameError):
"""
Raised by compile_fun when function requires symbols not yet defined.
This typically occurs when compilation is applied before all required
symbols (variables, functions, classes) have been defined in the scope.
"""
class UnsupportedForCompilation(TypeError):
"""
Raised by compile_fun when the decorated target is not supported.
Only function objects can be compiled. Other types (classes, modules,
built-ins, etc.) are not supported.
"""
class SourceUnavailable(OSError):
"""
Raised by compile_fun when function source code is not available.
This occurs when inspect.getsource() cannot retrieve the source code,
typically for built-in functions, C extensions, or functions defined
in interactive sessions without source preservation.
"""from makefun import compile_fun
@compile_fun
def secret_algorithm(x: int, y: int) -> int:
"""Perform secret calculation."""
# Complex implementation that we want to hide
intermediate = x * 2 + y
result = intermediate ** 2 - x
return result % 1000
# Function works normally
print(secret_algorithm(5, 3)) # Result: 121
# Source code is preserved for reference
print(secret_algorithm.__source__)
# Shows the original function definition
# But debugger cannot step into the implementation
# (implementation is compiled bytecode, not original source)from makefun import compile_fun
# Compile with recursive compilation disabled
@compile_fun(recurse=False)
def simple_function(x: int) -> int:
"""Simple function without recursive compilation."""
return x * 2
# Compile with exception list
def helper_function(x):
return x + 1
@compile_fun(recurse=True, except_names=["helper_function"])
def main_function(x: int) -> int:
"""Main function that uses helper."""
return helper_function(x) * 2
print(main_function(5)) # 12
# main_function is compiled, but helper_function is notfrom makefun import compile_fun
# Direct application without parentheses
@compile_fun
def immediate_compilation(data: list) -> int:
"""Function compiled immediately."""
return sum(data) if data else 0
print(immediate_compilation([1, 2, 3, 4])) # 10from makefun import compile_fun
@compile_fun
def proprietary_calculation(values: list, config: dict) -> dict:
"""Proprietary algorithm for data processing."""
# Complex proprietary logic that should be hidden
weights = config.get("weights", [1.0] * len(values))
processed = []
for i, val in enumerate(values):
weight = weights[i] if i < len(weights) else 1.0
# Complex transformation
transformed = (val * weight + config.get("bias", 0)) ** config.get("power", 1)
processed.append(transformed)
return {
"processed_values": processed,
"total": sum(processed),
"average": sum(processed) / len(processed) if processed else 0,
"config_used": config
}
# Function works normally but implementation is hidden from debugger
config = {"weights": [1.5, 2.0, 1.0], "bias": 10, "power": 1.2}
result = proprietary_calculation([100, 200, 150], config)
print(f"Total: {result['total']:.2f}")from makefun import compile_fun
def helper1(x):
return x * 2
def helper2(x):
return x + 10
@compile_fun(recurse=True)
def main_with_helpers(x: int) -> int:
"""Function that uses helper functions."""
# Both helper functions will be compiled recursively
intermediate = helper1(x)
return helper2(intermediate)
print(main_with_helpers(5)) # 20 (5*2 + 10)
# All functions in the closure are compiled
# main_with_helpers, helper1, and helper2 are all masked from debuggerfrom makefun import compile_fun
def public_utility(x):
"""This should remain debuggable."""
return x ** 2
def private_helper(x):
"""This should be hidden."""
return x * 3.14159
@compile_fun(recurse=True, except_names=["public_utility"])
def mixed_function(x: float) -> float:
"""Function with mixed compilation needs."""
# public_utility remains debuggable
# private_helper gets compiled and hidden
squared = public_utility(x)
return private_helper(squared)
print(mixed_function(2.0)) # ~12.57
# public_utility can be debugged, private_helper cannotfrom makefun import compile_fun, UnsupportedForCompilation, UndefinedSymbolError, SourceUnavailable
# Trying to compile non-function
try:
compiled_class = compile_fun(str) # str is not a function
except UnsupportedForCompilation as e:
print(f"Cannot compile non-function: {e}")
# Undefined symbol error
def function_with_undefined_ref():
return undefined_variable # This variable doesn't exist
try:
compiled_func = compile_fun(function_with_undefined_ref)
except UndefinedSymbolError as e:
print(f"Undefined symbol: {e}")
# Built-in function source unavailable
try:
compiled_builtin = compile_fun(len) # Built-in function
except SourceUnavailable as e:
print(f"Source not available: {e}")from makefun import compile_fun, create_function, with_signature
def secret_implementation(name, age, location):
"""Secret implementation logic."""
# Complex logic we want to hide
score = len(name) * age + hash(location) % 1000
return f"Score for {name}: {score}"
# First create function with specific signature
public_func = create_function("calculate_score(person_name: str, person_age: int, city: str = 'Unknown')",
secret_implementation)
# Then compile to hide implementation
@compile_fun
def compiled_calculator(person_name: str, person_age: int, city: str = 'Unknown') -> str:
return public_func(person_name, person_age, city)
print(compiled_calculator("Alice", 25, "New York"))
# Function works but implementation is hidden from debuggerfrom makefun import compile_fun
class DataProcessor:
"""Public API class with hidden implementations."""
@compile_fun
def _internal_algorithm(self, data: list) -> list:
"""Internal algorithm that should be hidden."""
# Proprietary processing logic
return [x * 2 + 1 for x in data if x > 0]
@compile_fun
def _optimization_step(self, data: list) -> list:
"""Internal optimization that should be hidden."""
# Complex optimization logic
return sorted(data, reverse=True)[:10]
def process(self, data: list) -> list:
"""Public API method - not compiled."""
# This method remains debuggable for users
if not data:
return []
# Internal methods are compiled and hidden
processed = self._internal_algorithm(data)
optimized = self._optimization_step(processed)
return optimized
# Usage
processor = DataProcessor()
result = processor.process([1, -2, 3, 4, -5, 6])
print(result)
# Users can debug process() method but not the internal algorithmsThe compilation feature is particularly useful for distinguishing between development and production environments:
from makefun import compile_fun
import os
# Conditional compilation based on environment
PRODUCTION = os.getenv("ENVIRONMENT") == "production"
def apply_compilation(func):
"""Apply compilation only in production."""
if PRODUCTION:
return compile_fun(func)
return func
@apply_compilation
def sensitive_algorithm(data: dict) -> dict:
"""Algorithm that should be hidden in production."""
# Development: debuggable
# Production: compiled and hidden
return {"processed": True, "data_size": len(data)}Important: Function compilation does NOT improve performance. According to Python's design principles, compiled bytecode runs at the same speed as interpreted code. The primary purpose is to hide implementation details during debugging sessions.
from makefun import compile_fun
import time
def regular_function(n: int) -> int:
"""Regular function for performance comparison."""
return sum(i * i for i in range(n))
@compile_fun
def compiled_function(n: int) -> int:
"""Compiled function for performance comparison."""
return sum(i * i for i in range(n))
# Performance is identical
n = 10000
start = time.time()
result1 = regular_function(n)
time1 = time.time() - start
start = time.time()
result2 = compiled_function(n)
time2 = time.time() - start
print(f"Regular: {time1:.6f}s, Compiled: {time2:.6f}s")
print(f"Results equal: {result1 == result2}")
# Performance difference is negligibleInstall with Tessl CLI
npx tessl i tessl/pypi-makefun