or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

application-framework.mdarray-types.mdcolab-integration.mddataclass-enhancements.mdindex.mdnumpy-utilities.mdpath-operations.mdpython-utilities.mdtree-manipulation.md

python-utilities.mddocs/

0

# Python Utilities (epy)

1

2

Collection of general-purpose Python utilities including environment detection, iteration helpers, text processing, error handling, lazy imports, and language feature enhancements for robust Python development.

3

4

## Capabilities

5

6

### Environment Detection

7

8

Utilities for detecting the current Python execution environment.

9

10

```python { .api }

11

def is_notebook() -> bool:

12

"""

13

Detect if running in a Jupyter notebook environment.

14

15

Returns:

16

True if running in Jupyter notebook, False otherwise

17

"""

18

19

def is_test() -> bool:

20

"""

21

Detect if running in a test environment.

22

23

Returns:

24

True if running in test context, False otherwise

25

"""

26

```

27

28

### Import Management

29

30

Advanced import utilities for lazy loading and module management.

31

32

```python { .api }

33

def lazy_imports(**modules) -> Any:

34

"""

35

Create lazy import proxy objects for deferred loading.

36

37

Args:

38

**modules: Module names and import paths

39

40

Returns:

41

Lazy import proxy object

42

43

Example:

44

np = lazy_imports(numpy='numpy')

45

# numpy only imported when first used

46

"""

47

48

def lazy_api_imports(**api_modules) -> Any:

49

"""

50

Create lazy API import utilities for modular APIs.

51

52

Args:

53

**api_modules: API module definitions

54

55

Returns:

56

Lazy API import system

57

"""

58

59

def binary_adhoc(module_path: str) -> Any:

60

"""

61

Import binary modules ad-hoc for specialized use cases.

62

63

Args:

64

module_path: Path to binary module

65

66

Returns:

67

Imported binary module

68

"""

69

```

70

71

### Iteration Utilities

72

73

Enhanced iteration functions for data processing.

74

75

```python { .api }

76

def groupby(

77

iterable: Iterable[T],

78

key: Callable[[T], K] | None = None

79

) -> dict[K, list[T]]:

80

"""

81

Group iterable elements by key function.

82

83

Args:

84

iterable: Items to group

85

key: Function to generate grouping key

86

87

Returns:

88

Dictionary mapping keys to grouped items

89

"""

90

91

def splitby(

92

iterable: Iterable[T],

93

condition: Callable[[T], bool]

94

) -> tuple[list[T], list[T]]:

95

"""

96

Split iterable into two lists based on condition.

97

98

Args:

99

iterable: Items to split

100

condition: Function returning True/False for each item

101

102

Returns:

103

Tuple of (items_matching, items_not_matching)

104

"""

105

106

def zip_dict(*dicts: dict) -> dict[Any, tuple]:

107

"""

108

Zip multiple dictionaries by matching keys.

109

110

Args:

111

*dicts: Dictionaries to zip together

112

113

Returns:

114

Dictionary with keys mapped to tuples of values

115

"""

116

```

117

118

### Language Feature Enhancements

119

120

Utilities for enhancing Python language features.

121

122

```python { .api }

123

def frozen(cls: type) -> type:

124

"""

125

Decorator to make class instances immutable.

126

127

Args:

128

cls: Class to make frozen

129

130

Returns:

131

Frozen class where instances cannot be modified

132

"""

133

134

def is_namedtuple(obj: Any) -> bool:

135

"""

136

Check if object is a named tuple.

137

138

Args:

139

obj: Object to check

140

141

Returns:

142

True if object is a named tuple, False otherwise

143

"""

144

145

def issubclass(obj: Any, base: type) -> bool:

146

"""

147

Safe subclass checking that handles non-class objects.

148

149

Args:

150

obj: Object to check

151

base: Base class to check against

152

153

Returns:

154

True if obj is subclass of base, False otherwise

155

"""

156

157

def wraps_cls(cls: type) -> Callable:

158

"""

159

Class-based version of functools.wraps.

160

161

Args:

162

cls: Class to wrap

163

164

Returns:

165

Decorator function for wrapping classes

166

"""

167

168

class StrEnum(str, Enum):

169

"""

170

String enumeration that inherits from both str and Enum.

171

172

Allows enum values to be used as strings while maintaining enum benefits.

173

"""

174

pass

175

```

176

177

### Context Management

178

179

Enhanced context management utilities.

180

181

```python { .api }

182

class ContextManager:

183

"""

184

Enhanced context manager with additional functionality.

185

"""

186

def __init__(self, enter_fn: Callable, exit_fn: Callable) -> None: ...

187

def __enter__(self) -> Any: ...

188

def __exit__(self, exc_type, exc_val, exc_tb) -> None: ...

189

190

class ExitStack:

191

"""

192

Enhanced exit stack for managing multiple context managers.

193

"""

194

def __init__(self) -> None: ...

195

def enter_context(self, cm: Any) -> Any: ...

196

def push(self, exit_fn: Callable) -> None: ...

197

def close(self) -> None: ...

198

```

199

200

### Error Handling

201

202

Utilities for enhanced error handling and exception management.

203

204

```python { .api }

205

def reraise(

206

exception: Exception,

207

message: str | None = None

208

) -> NoReturn:

209

"""

210

Reraise exception with optional additional message.

211

212

Args:

213

exception: Exception to reraise

214

message: Additional message to include

215

216

Raises:

217

The provided exception with enhanced context

218

"""

219

220

def maybe_reraise(

221

exception: Exception,

222

condition: bool,

223

message: str | None = None

224

) -> None:

225

"""

226

Conditionally reraise exception based on condition.

227

228

Args:

229

exception: Exception to potentially reraise

230

condition: Whether to reraise the exception

231

message: Additional message if reraising

232

233

Raises:

234

The provided exception if condition is True

235

"""

236

```

237

238

### Text Processing

239

240

Text manipulation and formatting utilities.

241

242

```python { .api }

243

def dedent(text: str) -> str:

244

"""

245

Remove leading whitespace from text while preserving relative indentation.

246

247

Args:

248

text: Text to dedent

249

250

Returns:

251

Dedented text

252

"""

253

254

def diff_str(str1: str, str2: str) -> str:

255

"""

256

Generate visual diff between two strings.

257

258

Args:

259

str1: First string

260

str2: Second string

261

262

Returns:

263

String showing differences between inputs

264

"""

265

266

def pprint(obj: Any, **kwargs) -> None:

267

"""

268

Pretty print object with enhanced formatting.

269

270

Args:

271

obj: Object to pretty print

272

**kwargs: Additional formatting options

273

"""

274

275

def pretty_repr(obj: Any) -> str:

276

"""

277

Generate pretty string representation of object.

278

279

Args:

280

obj: Object to represent

281

282

Returns:

283

Pretty string representation

284

"""

285

286

def pretty_repr_top_level(obj: Any) -> str:

287

"""

288

Generate pretty representation for top-level objects.

289

290

Args:

291

obj: Object to represent

292

293

Returns:

294

Top-level pretty representation

295

"""

296

297

class Lines:

298

"""

299

Utility class for manipulating text lines.

300

"""

301

def __init__(self, lines: list[str] | str) -> None: ...

302

def __str__(self) -> str: ...

303

def __len__(self) -> int: ...

304

def append(self, line: str) -> None: ...

305

def join(self, separator: str = '\\n') -> str: ...

306

```

307

308

### Regular Expression Utilities

309

310

Advanced regex utilities for text processing.

311

312

```python { .api }

313

def reverse_fstring(

314

template: str,

315

text: str

316

) -> dict[str, str]:

317

"""

318

Reverse f-string formatting to extract values.

319

320

Args:

321

template: F-string template (e.g., "Hello {name}, age {age}")

322

text: Formatted text (e.g., "Hello Alice, age 25")

323

324

Returns:

325

Dictionary of extracted values (e.g., {"name": "Alice", "age": "25"})

326

"""

327

```

328

329

### Utility Modules

330

331

Additional modules providing specialized functionality.

332

333

```python { .api }

334

_internal: ModuleType # Internal utilities module

335

typing: ModuleType # Enhanced typing utilities

336

testing: ModuleType # Testing utilities (when pytest available)

337

```

338

339

## Usage Examples

340

341

### Environment Detection

342

343

```python

344

from etils import epy

345

346

# Detect execution environment

347

if epy.is_notebook():

348

print("Running in Jupyter notebook")

349

# Use notebook-specific features

350

from IPython.display import display

351

else:

352

print("Running in regular Python")

353

354

if epy.is_test():

355

print("Running in test environment")

356

# Use test-specific configurations

357

DEBUG = True

358

else:

359

DEBUG = False

360

```

361

362

### Lazy Imports

363

364

```python

365

from etils import epy

366

367

# Lazy import expensive modules

368

lazy_modules = epy.lazy_imports(

369

np='numpy',

370

pd='pandas',

371

plt='matplotlib.pyplot'

372

)

373

374

# Modules only imported when first accessed

375

data = lazy_modules.np.array([1, 2, 3]) # numpy imported here

376

df = lazy_modules.pd.DataFrame(data) # pandas imported here

377

378

# Lazy API imports for modular systems

379

api = epy.lazy_api_imports(

380

vision='my_package.vision',

381

nlp='my_package.nlp'

382

)

383

```

384

385

### Iteration Utilities

386

387

```python

388

from etils import epy

389

390

# Group items by category

391

items = [

392

{'name': 'apple', 'type': 'fruit'},

393

{'name': 'carrot', 'type': 'vegetable'},

394

{'name': 'banana', 'type': 'fruit'},

395

{'name': 'broccoli', 'type': 'vegetable'}

396

]

397

398

grouped = epy.groupby(items, key=lambda x: x['type'])

399

# Result: {

400

# 'fruit': [{'name': 'apple', 'type': 'fruit'}, {'name': 'banana', 'type': 'fruit'}],

401

# 'vegetable': [{'name': 'carrot', 'type': 'vegetable'}, {'name': 'broccoli', 'type': 'vegetable'}]

402

# }

403

404

# Split by condition

405

numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

406

evens, odds = epy.splitby(numbers, lambda x: x % 2 == 0)

407

# evens: [2, 4, 6, 8, 10], odds: [1, 3, 5, 7, 9]

408

409

# Zip dictionaries

410

dict1 = {'a': 1, 'b': 2, 'c': 3}

411

dict2 = {'a': 'x', 'b': 'y', 'c': 'z'}

412

zipped = epy.zip_dict(dict1, dict2)

413

# Result: {'a': (1, 'x'), 'b': (2, 'y'), 'c': (3, 'z')}

414

```

415

416

### Language Enhancements

417

418

```python

419

from etils import epy

420

421

# Create immutable classes

422

@epy.frozen

423

class Point:

424

def __init__(self, x, y):

425

self.x = x

426

self.y = y

427

428

point = Point(1, 2)

429

# point.x = 3 # Would raise error - object is frozen

430

431

# String enums

432

class Color(epy.StrEnum):

433

RED = 'red'

434

GREEN = 'green'

435

BLUE = 'blue'

436

437

# Can use as string or enum

438

color = Color.RED

439

print(f"Color: {color}") # Works as string

440

assert color == 'red' # String comparison works

441

442

# Safe subclass checking

443

class Animal: pass

444

class Dog(Animal): pass

445

446

assert epy.issubclass(Dog, Animal) # True

447

assert not epy.issubclass("not a class", Animal) # False, no error

448

449

# Named tuple detection

450

from collections import namedtuple

451

Person = namedtuple('Person', ['name', 'age'])

452

person = Person('Alice', 25)

453

454

assert epy.is_namedtuple(person) # True

455

assert not epy.is_namedtuple({'name': 'Bob'}) # False

456

```

457

458

### Error Handling

459

460

```python

461

from etils import epy

462

463

def risky_operation(data):

464

try:

465

return process_data(data)

466

except ValueError as e:

467

# Reraise with additional context

468

epy.reraise(e, "Failed to process data in risky_operation")

469

470

def conditional_error_handling(data, strict_mode=False):

471

try:

472

return validate_data(data)

473

except ValidationError as e:

474

# Only reraise in strict mode

475

epy.maybe_reraise(e, strict_mode, "Validation failed in strict mode")

476

return None # Return None if not strict

477

```

478

479

### Text Processing

480

481

```python

482

from etils import epy

483

484

# Dedent multi-line strings

485

code = '''

486

def hello():

487

print("Hello, world!")

488

return True

489

'''

490

clean_code = epy.dedent(code)

491

# Removes leading whitespace while preserving structure

492

493

# Pretty printing

494

complex_data = {

495

'model': {'layers': [64, 128, 256], 'dropout': 0.1},

496

'training': {'epochs': 100, 'batch_size': 32}

497

}

498

epy.pprint(complex_data) # Enhanced pretty printing

499

500

# String diffing

501

old_text = "The quick brown fox"

502

new_text = "The quick red fox"

503

diff = epy.diff_str(old_text, new_text)

504

print(diff) # Shows differences visually

505

506

# Reverse f-strings

507

template = "Hello {name}, you are {age} years old"

508

text = "Hello Alice, you are 25 years old"

509

values = epy.reverse_fstring(template, text)

510

# Result: {'name': 'Alice', 'age': '25'}

511

```

512

513

### Context Management

514

515

```python

516

from etils import epy

517

518

# Enhanced context manager

519

def my_context_manager():

520

print("Entering context")

521

try:

522

yield "context value"

523

finally:

524

print("Exiting context")

525

526

with epy.ContextManager(

527

enter_fn=lambda: print("Setup"),

528

exit_fn=lambda: print("Cleanup")

529

):

530

print("In context")

531

532

# Exit stack for multiple resources

533

with epy.ExitStack() as stack:

534

file1 = stack.enter_context(open('file1.txt'))

535

file2 = stack.enter_context(open('file2.txt'))

536

# Both files automatically closed

537

```

538

539

### Line Processing

540

541

```python

542

from etils import epy

543

544

# Work with text lines

545

lines = epy.Lines([

546

"Line 1",

547

"Line 2",

548

"Line 3"

549

])

550

551

lines.append("Line 4")

552

text = lines.join('\\n') # Join with newlines

553

print(f"Total lines: {len(lines)}")

554

555

# From string

556

content = "Line A\\nLine B\\nLine C"

557

lines = epy.Lines(content)

558

# Automatically splits on newlines

559

```