or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

core-implementation.mdindex.mdipython-integration.mdoutput-capture.mdpermanent-redirection.mdsystem-integration.md

permanent-redirection.mddocs/

0

# Permanent Redirection

1

2

Enable and disable permanent C-level output forwarding without context managers, useful for global configuration and long-running applications.

3

4

## Capabilities

5

6

### Enable Permanent Redirection

7

8

Start permanent forwarding of all C-level output to Python sys streams.

9

10

```python { .api }

11

def sys_pipes_forever(encoding='utf-8', bufsize=None):

12

"""Redirect all C output to sys.stdout/err permanently.

13

14

Args:

15

encoding: Text encoding for output (default: 'utf-8')

16

bufsize: Pipe buffer size in bytes (default: auto-detected)

17

18

Note:

19

This is not a context manager; it turns on C-forwarding permanently

20

until stop_sys_pipes() is called.

21

"""

22

```

23

24

Example usage:

25

26

```python

27

from wurlitzer import sys_pipes_forever

28

29

# Enable permanent redirection at application startup

30

sys_pipes_forever()

31

32

# All subsequent C-level output is forwarded

33

c_library_function_1()

34

other_c_operations()

35

c_library_function_2()

36

37

# Output forwarding continues until explicitly stopped

38

```

39

40

### Disable Permanent Redirection

41

42

Stop permanent redirection and restore original C-level stream behavior.

43

44

```python { .api }

45

def stop_sys_pipes():

46

"""Stop permanent redirection started by sys_pipes_forever"""

47

```

48

49

Example usage:

50

51

```python

52

from wurlitzer import sys_pipes_forever, stop_sys_pipes

53

54

# Start permanent forwarding

55

sys_pipes_forever()

56

57

# ... application runs with C output forwarded ...

58

59

# Stop forwarding at application shutdown or when no longer needed

60

stop_sys_pipes()

61

62

# C output now goes back to original destinations

63

```

64

65

### Thread-Safe Global State

66

67

The permanent redirection system uses thread-safe locks to manage global state.

68

69

```python

70

from wurlitzer import sys_pipes_forever, stop_sys_pipes

71

import threading

72

73

def worker_function():

74

# Multiple threads can safely call these functions

75

sys_pipes_forever() # Only activates once globally

76

77

c_work_function()

78

79

stop_sys_pipes() # Only deactivates when last thread calls it

80

81

# Safe in multi-threaded environments

82

threads = [threading.Thread(target=worker_function) for _ in range(3)]

83

for t in threads:

84

t.start()

85

for t in threads:

86

t.join()

87

```

88

89

## Usage Patterns

90

91

### Application Initialization

92

93

Configure C-level output forwarding during application startup:

94

95

```python

96

from wurlitzer import sys_pipes_forever

97

import logging

98

99

def initialize_app():

100

# Setup logging

101

logging.basicConfig(level=logging.INFO)

102

103

# Enable C output forwarding for entire application

104

sys_pipes_forever()

105

106

print("Application initialized with C output forwarding")

107

108

def main():

109

initialize_app()

110

111

# All C library calls throughout the application

112

# will have their output forwarded to sys.stdout/stderr

113

run_application_logic()

114

```

115

116

### Service/Daemon Applications

117

118

Long-running services that need consistent C output handling:

119

120

```python

121

import signal

122

import sys

123

from wurlitzer import sys_pipes_forever, stop_sys_pipes

124

125

class ServiceApplication:

126

def __init__(self):

127

# Enable C output forwarding for service lifetime

128

sys_pipes_forever()

129

130

def start(self):

131

# Setup signal handlers for clean shutdown

132

signal.signal(signal.SIGTERM, self._shutdown)

133

signal.signal(signal.SIGINT, self._shutdown)

134

135

# Service main loop

136

while self.running:

137

self.process_requests()

138

139

def _shutdown(self, signum, frame):

140

print("Shutting down service...")

141

stop_sys_pipes()

142

self.running = False

143

sys.exit(0)

144

145

def process_requests(self):

146

# C library calls have output forwarded automatically

147

c_request_processor.handle_batch()

148

```

149

150

### Testing Setup/Teardown

151

152

Configure test environments with global C output forwarding:

153

154

```python

155

import pytest

156

from wurlitzer import sys_pipes_forever, stop_sys_pipes

157

158

@pytest.fixture(scope="session", autouse=True)

159

def setup_c_output_forwarding():

160

"""Enable C output forwarding for entire test session"""

161

sys_pipes_forever()

162

yield

163

stop_sys_pipes()

164

165

def test_c_function_1():

166

# C output automatically forwarded, captured by pytest

167

c_function_under_test()

168

169

def test_c_function_2():

170

# All tests benefit from automatic C output forwarding

171

another_c_function()

172

```

173

174

### Library Initialization

175

176

Enable forwarding when importing libraries that use C extensions:

177

178

```python

179

# mylib/__init__.py

180

from wurlitzer import sys_pipes_forever

181

182

# Automatically enable C output forwarding when library is imported

183

sys_pipes_forever()

184

185

from .core import main_functions

186

from .extensions import c_extensions

187

188

__all__ = ['main_functions', 'c_extensions']

189

```

190

191

### Conditional Activation

192

193

Enable permanent redirection based on environment or configuration:

194

195

```python

196

import os

197

from wurlitzer import sys_pipes_forever

198

199

def configure_output_handling():

200

# Enable based on environment variable

201

if os.getenv('ENABLE_C_OUTPUT_FORWARDING', '').lower() == 'true':

202

sys_pipes_forever()

203

print("C output forwarding enabled")

204

205

# Or based on configuration file

206

if config.get('debug', {}).get('capture_c_output', False):

207

sys_pipes_forever()

208

print("Debug mode: C output forwarding enabled")

209

210

# Call during application setup

211

configure_output_handling()

212

```

213

214

## State Management

215

216

### Idempotent Operations

217

218

Multiple calls to sys_pipes_forever() are safe and idempotent:

219

220

```python

221

from wurlitzer import sys_pipes_forever, stop_sys_pipes

222

223

# Multiple calls don't create multiple redirections

224

sys_pipes_forever() # Enables forwarding

225

sys_pipes_forever() # No additional effect

226

sys_pipes_forever() # Still no additional effect

227

228

stop_sys_pipes() # Disables forwarding

229

stop_sys_pipes() # Safe to call multiple times

230

```

231

232

### Status Checking

233

234

Check if permanent redirection is currently active:

235

236

```python

237

from wurlitzer import sys_pipes_forever, stop_sys_pipes

238

import wurlitzer

239

240

# Check global state (internal variable)

241

def is_permanent_forwarding_active():

242

return wurlitzer._mighty_wurlitzer is not None

243

244

# Example usage

245

if not is_permanent_forwarding_active():

246

sys_pipes_forever()

247

248

# Later...

249

if is_permanent_forwarding_active():

250

print("C output is being forwarded")

251

stop_sys_pipes()

252

```

253

254

### Context Integration

255

256

Combine permanent redirection with temporary context managers:

257

258

```python

259

from wurlitzer import sys_pipes_forever, stop_sys_pipes, pipes

260

261

# Global forwarding for most operations

262

sys_pipes_forever()

263

264

# Temporary override for specific capture

265

with pipes() as (out, err):

266

# This temporarily overrides the permanent forwarding

267

special_c_function()

268

269

captured_output = out.read()

270

271

# Back to permanent forwarding after context manager exits

272

normal_c_operations()

273

```