or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

compilation.mddecorators.mdfunction-creation.mdindex.mdpartial.mdsignature-utils.mdwrapping.md

compilation.mddocs/

0

# Compilation Utilities

1

2

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.

3

4

```python

5

from typing import Union, Callable, Iterable

6

```

7

8

## Capabilities

9

10

### Function Compilation Decorator

11

12

Decorator that compiles functions to mask their implementation from debuggers while preserving source code access.

13

14

```python { .api }

15

def compile_fun(recurse: Union[bool, Callable] = True,

16

except_names: Iterable[str] = ()) -> Union[Callable, Callable[[Callable], Callable]]:

17

"""

18

Decorator to compile functions for debugging convenience.

19

20

Compiles any existing function so that users can't debug through it,

21

which can be handy to mask some code from users for convenience.

22

The source code is preserved in the __source__ attribute.

23

24

Parameters:

25

- recurse: Union[bool, Callable], default True

26

If True, recursively compile referenced functions in closure.

27

If Callable, apply compilation immediately (no-args decorator usage).

28

- except_names: Iterable[str], default ()

29

Function names to exclude from recursive compilation

30

31

Returns:

32

Union[Callable, Callable[[Callable], Callable]]:

33

- If called with parentheses: returns decorator function

34

- If called without parentheses: returns compiled function directly

35

36

Raises:

37

UnsupportedForCompilation: If target is not a function

38

UndefinedSymbolError: If function references undefined symbols

39

SourceUnavailable: If function source code cannot be retrieved

40

41

Note:

42

- Compilation does not improve performance (per Python design)

43

- Primary use is hiding implementation details during debugging

44

- Source code remains available via __source__ attribute

45

- Recursively compiles closure functions by default

46

"""

47

```

48

49

### Exception Classes

50

51

```python { .api }

52

class UndefinedSymbolError(NameError):

53

"""

54

Raised by compile_fun when function requires symbols not yet defined.

55

56

This typically occurs when compilation is applied before all required

57

symbols (variables, functions, classes) have been defined in the scope.

58

"""

59

60

class UnsupportedForCompilation(TypeError):

61

"""

62

Raised by compile_fun when the decorated target is not supported.

63

64

Only function objects can be compiled. Other types (classes, modules,

65

built-ins, etc.) are not supported.

66

"""

67

68

class SourceUnavailable(OSError):

69

"""

70

Raised by compile_fun when function source code is not available.

71

72

This occurs when inspect.getsource() cannot retrieve the source code,

73

typically for built-in functions, C extensions, or functions defined

74

in interactive sessions without source preservation.

75

"""

76

```

77

78

### Usage Examples

79

80

#### Basic Function Compilation

81

82

```python

83

from makefun import compile_fun

84

85

@compile_fun

86

def secret_algorithm(x: int, y: int) -> int:

87

"""Perform secret calculation."""

88

# Complex implementation that we want to hide

89

intermediate = x * 2 + y

90

result = intermediate ** 2 - x

91

return result % 1000

92

93

# Function works normally

94

print(secret_algorithm(5, 3)) # Result: 121

95

96

# Source code is preserved for reference

97

print(secret_algorithm.__source__)

98

# Shows the original function definition

99

100

# But debugger cannot step into the implementation

101

# (implementation is compiled bytecode, not original source)

102

```

103

104

#### Compilation with Parameters

105

106

```python

107

from makefun import compile_fun

108

109

# Compile with recursive compilation disabled

110

@compile_fun(recurse=False)

111

def simple_function(x: int) -> int:

112

"""Simple function without recursive compilation."""

113

return x * 2

114

115

# Compile with exception list

116

def helper_function(x):

117

return x + 1

118

119

@compile_fun(recurse=True, except_names=["helper_function"])

120

def main_function(x: int) -> int:

121

"""Main function that uses helper."""

122

return helper_function(x) * 2

123

124

print(main_function(5)) # 12

125

# main_function is compiled, but helper_function is not

126

```

127

128

#### No-Arguments Decorator Usage

129

130

```python

131

from makefun import compile_fun

132

133

# Direct application without parentheses

134

@compile_fun

135

def immediate_compilation(data: list) -> int:

136

"""Function compiled immediately."""

137

return sum(data) if data else 0

138

139

print(immediate_compilation([1, 2, 3, 4])) # 10

140

```

141

142

#### Hiding Complex Logic

143

144

```python

145

from makefun import compile_fun

146

147

@compile_fun

148

def proprietary_calculation(values: list, config: dict) -> dict:

149

"""Proprietary algorithm for data processing."""

150

# Complex proprietary logic that should be hidden

151

weights = config.get("weights", [1.0] * len(values))

152

153

processed = []

154

for i, val in enumerate(values):

155

weight = weights[i] if i < len(weights) else 1.0

156

# Complex transformation

157

transformed = (val * weight + config.get("bias", 0)) ** config.get("power", 1)

158

processed.append(transformed)

159

160

return {

161

"processed_values": processed,

162

"total": sum(processed),

163

"average": sum(processed) / len(processed) if processed else 0,

164

"config_used": config

165

}

166

167

# Function works normally but implementation is hidden from debugger

168

config = {"weights": [1.5, 2.0, 1.0], "bias": 10, "power": 1.2}

169

result = proprietary_calculation([100, 200, 150], config)

170

print(f"Total: {result['total']:.2f}")

171

```

172

173

#### Recursive Compilation Example

174

175

```python

176

from makefun import compile_fun

177

178

def helper1(x):

179

return x * 2

180

181

def helper2(x):

182

return x + 10

183

184

@compile_fun(recurse=True)

185

def main_with_helpers(x: int) -> int:

186

"""Function that uses helper functions."""

187

# Both helper functions will be compiled recursively

188

intermediate = helper1(x)

189

return helper2(intermediate)

190

191

print(main_with_helpers(5)) # 20 (5*2 + 10)

192

193

# All functions in the closure are compiled

194

# main_with_helpers, helper1, and helper2 are all masked from debugger

195

```

196

197

#### Selective Compilation

198

199

```python

200

from makefun import compile_fun

201

202

def public_utility(x):

203

"""This should remain debuggable."""

204

return x ** 2

205

206

def private_helper(x):

207

"""This should be hidden."""

208

return x * 3.14159

209

210

@compile_fun(recurse=True, except_names=["public_utility"])

211

def mixed_function(x: float) -> float:

212

"""Function with mixed compilation needs."""

213

# public_utility remains debuggable

214

# private_helper gets compiled and hidden

215

squared = public_utility(x)

216

return private_helper(squared)

217

218

print(mixed_function(2.0)) # ~12.57

219

# public_utility can be debugged, private_helper cannot

220

```

221

222

#### Error Handling

223

224

```python

225

from makefun import compile_fun, UnsupportedForCompilation, UndefinedSymbolError, SourceUnavailable

226

227

# Trying to compile non-function

228

try:

229

compiled_class = compile_fun(str) # str is not a function

230

except UnsupportedForCompilation as e:

231

print(f"Cannot compile non-function: {e}")

232

233

# Undefined symbol error

234

def function_with_undefined_ref():

235

return undefined_variable # This variable doesn't exist

236

237

try:

238

compiled_func = compile_fun(function_with_undefined_ref)

239

except UndefinedSymbolError as e:

240

print(f"Undefined symbol: {e}")

241

242

# Built-in function source unavailable

243

try:

244

compiled_builtin = compile_fun(len) # Built-in function

245

except SourceUnavailable as e:

246

print(f"Source not available: {e}")

247

```

248

249

#### Integration with Other Makefun Features

250

251

```python

252

from makefun import compile_fun, create_function, with_signature

253

254

def secret_implementation(name, age, location):

255

"""Secret implementation logic."""

256

# Complex logic we want to hide

257

score = len(name) * age + hash(location) % 1000

258

return f"Score for {name}: {score}"

259

260

# First create function with specific signature

261

public_func = create_function("calculate_score(person_name: str, person_age: int, city: str = 'Unknown')",

262

secret_implementation)

263

264

# Then compile to hide implementation

265

@compile_fun

266

def compiled_calculator(person_name: str, person_age: int, city: str = 'Unknown') -> str:

267

return public_func(person_name, person_age, city)

268

269

print(compiled_calculator("Alice", 25, "New York"))

270

# Function works but implementation is hidden from debugger

271

```

272

273

#### Library Development Pattern

274

275

```python

276

from makefun import compile_fun

277

278

class DataProcessor:

279

"""Public API class with hidden implementations."""

280

281

@compile_fun

282

def _internal_algorithm(self, data: list) -> list:

283

"""Internal algorithm that should be hidden."""

284

# Proprietary processing logic

285

return [x * 2 + 1 for x in data if x > 0]

286

287

@compile_fun

288

def _optimization_step(self, data: list) -> list:

289

"""Internal optimization that should be hidden."""

290

# Complex optimization logic

291

return sorted(data, reverse=True)[:10]

292

293

def process(self, data: list) -> list:

294

"""Public API method - not compiled."""

295

# This method remains debuggable for users

296

if not data:

297

return []

298

299

# Internal methods are compiled and hidden

300

processed = self._internal_algorithm(data)

301

optimized = self._optimization_step(processed)

302

return optimized

303

304

# Usage

305

processor = DataProcessor()

306

result = processor.process([1, -2, 3, 4, -5, 6])

307

print(result)

308

309

# Users can debug process() method but not the internal algorithms

310

```

311

312

### Development vs Production Usage

313

314

The compilation feature is particularly useful for distinguishing between development and production environments:

315

316

```python

317

from makefun import compile_fun

318

import os

319

320

# Conditional compilation based on environment

321

PRODUCTION = os.getenv("ENVIRONMENT") == "production"

322

323

def apply_compilation(func):

324

"""Apply compilation only in production."""

325

if PRODUCTION:

326

return compile_fun(func)

327

return func

328

329

@apply_compilation

330

def sensitive_algorithm(data: dict) -> dict:

331

"""Algorithm that should be hidden in production."""

332

# Development: debuggable

333

# Production: compiled and hidden

334

return {"processed": True, "data_size": len(data)}

335

```

336

337

### Performance Considerations

338

339

**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.

340

341

```python

342

from makefun import compile_fun

343

import time

344

345

def regular_function(n: int) -> int:

346

"""Regular function for performance comparison."""

347

return sum(i * i for i in range(n))

348

349

@compile_fun

350

def compiled_function(n: int) -> int:

351

"""Compiled function for performance comparison."""

352

return sum(i * i for i in range(n))

353

354

# Performance is identical

355

n = 10000

356

357

start = time.time()

358

result1 = regular_function(n)

359

time1 = time.time() - start

360

361

start = time.time()

362

result2 = compiled_function(n)

363

time2 = time.time() - start

364

365

print(f"Regular: {time1:.6f}s, Compiled: {time2:.6f}s")

366

print(f"Results equal: {result1 == result2}")

367

# Performance difference is negligible

368

```