or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

application-wrappers.mdasync-integration.mdconfiguration.mdevents.mdindex.mdlogging.mdmiddleware.mdserver-execution.mdtypes.mdutilities.md

application-wrappers.mddocs/

0

# Application Wrappers

1

2

Wrapper classes that adapt ASGI and WSGI applications to Hypercorn's internal protocol interface. These wrappers handle protocol translation, request/response lifecycle management, and provide the bridge between applications and Hypercorn's event-driven architecture.

3

4

## Capabilities

5

6

### ASGI Application Wrapper

7

8

Wrapper for ASGI applications that provides the interface between ASGI applications and Hypercorn's internal protocol handling.

9

10

```python { .api }

11

class ASGIWrapper:

12

"""

13

Wrapper for ASGI applications.

14

15

Adapts ASGI applications to Hypercorn's internal protocol interface,

16

handling the ASGI application lifecycle and providing the necessary

17

sync_spawn and call_soon capabilities for ASGI compatibility.

18

"""

19

20

def __init__(self, app: ASGIFramework):

21

"""

22

Initialize ASGI wrapper.

23

24

Args:

25

app: ASGI application callable that follows the ASGI spec

26

"""

27

28

async def __call__(

29

self,

30

scope: Scope,

31

receive: ASGIReceiveCallable,

32

send: ASGISendCallable,

33

sync_spawn: Callable,

34

call_soon: Callable

35

):

36

"""

37

Execute the ASGI application.

38

39

Args:

40

scope: ASGI scope dictionary containing request information

41

receive: ASGI receive callable for getting request data

42

send: ASGI send callable for sending response data

43

sync_spawn: Function to spawn synchronous tasks

44

call_soon: Function to schedule tasks for immediate execution

45

46

The wrapper handles the ASGI application lifecycle, managing

47

the connection between Hypercorn's event-driven architecture

48

and the ASGI application interface.

49

"""

50

```

51

52

### WSGI Application Wrapper

53

54

Wrapper for WSGI applications that adapts them to work within Hypercorn's async environment, handling the synchronous WSGI interface within an async context.

55

56

```python { .api }

57

class WSGIWrapper:

58

"""

59

Wrapper for WSGI applications.

60

61

Adapts WSGI applications to work within Hypercorn's async environment

62

by handling the synchronous WSGI interface and translating between

63

WSGI's request/response model and ASGI's event-driven interface.

64

"""

65

66

def __init__(self, app: WSGIFramework, max_body_size: int):

67

"""

68

Initialize WSGI wrapper.

69

70

Args:

71

app: WSGI application callable following WSGI spec

72

max_body_size: Maximum request body size in bytes

73

"""

74

75

async def __call__(

76

self,

77

scope: Scope,

78

receive: ASGIReceiveCallable,

79

send: ASGISendCallable,

80

sync_spawn: Callable,

81

call_soon: Callable

82

):

83

"""

84

Execute the WSGI application.

85

86

Args:

87

scope: ASGI scope dictionary (converted to WSGI environ)

88

receive: ASGI receive callable for getting request data

89

send: ASGI send callable for sending response data

90

sync_spawn: Function to spawn synchronous tasks (used for WSGI execution)

91

call_soon: Function to schedule tasks for immediate execution

92

93

The wrapper translates between ASGI's async event model and

94

WSGI's synchronous request/response model, handling:

95

- Environ dictionary creation from ASGI scope

96

- Request body streaming and buffering

97

- Response handling and chunked encoding

98

- Synchronous execution within async context

99

"""

100

```

101

102

### Application Loading Exceptions

103

104

Exceptions raised during application loading and wrapping processes.

105

106

```python { .api }

107

class InvalidPathError(Exception):

108

"""

109

Raised when an invalid application path is provided.

110

111

This exception occurs when the application path cannot be

112

resolved to a valid ASGI or WSGI application, such as:

113

- Module import failures

114

- Missing application attributes

115

- Invalid application callable signatures

116

"""

117

```

118

119

## Framework Type Definitions

120

121

Type definitions for the application frameworks supported by the wrappers.

122

123

```python { .api }

124

# ASGI application interface

125

ASGIFramework = Callable[[Scope, ASGIReceiveCallable, ASGISendCallable], Awaitable[None]]

126

127

# WSGI application interface

128

WSGIFramework = Callable[[dict, Callable], Iterable[bytes]]

129

130

# ASGI scope types

131

Scope = HTTPScope | WebsocketScope | LifespanScope

132

133

# ASGI callable types

134

ASGIReceiveCallable = Callable[[], Awaitable[ASGIReceiveEvent]]

135

ASGISendCallable = Callable[[ASGISendEvent], Awaitable[None]]

136

```

137

138

## Usage Examples

139

140

### Direct ASGI Wrapper Usage

141

142

```python

143

from hypercorn.app_wrappers import ASGIWrapper

144

145

async def asgi_app(scope, receive, send):

146

"""Simple ASGI application"""

147

if scope['type'] == 'http':

148

await send({

149

'type': 'http.response.start',

150

'status': 200,

151

'headers': [[b'content-type', b'text/plain']],

152

})

153

await send({

154

'type': 'http.response.body',

155

'body': b'Hello from ASGI',

156

})

157

158

# Wrap the ASGI application

159

wrapper = ASGIWrapper(asgi_app)

160

161

# The wrapper is now ready for use by Hypercorn's internal protocol handlers

162

```

163

164

### Direct WSGI Wrapper Usage

165

166

```python

167

from hypercorn.app_wrappers import WSGIWrapper

168

169

def wsgi_app(environ, start_response):

170

"""Simple WSGI application"""

171

status = '200 OK'

172

headers = [('Content-Type', 'text/plain')]

173

start_response(status, headers)

174

return [b'Hello from WSGI']

175

176

# Wrap the WSGI application with body size limit

177

max_body_size = 16 * 1024 * 1024 # 16MB

178

wrapper = WSGIWrapper(wsgi_app, max_body_size)

179

180

# The wrapper is now ready for use by Hypercorn's internal protocol handlers

181

```

182

183

### Framework Detection and Wrapping

184

185

The wrappers are typically used internally by Hypercorn, but can be used directly for custom server implementations:

186

187

```python

188

from hypercorn.app_wrappers import ASGIWrapper, WSGIWrapper

189

from hypercorn.utils import is_asgi

190

191

def wrap_application(app, max_body_size=16*1024*1024):

192

"""Wrap application based on its type"""

193

if is_asgi(app):

194

return ASGIWrapper(app)

195

else:

196

return WSGIWrapper(app, max_body_size)

197

198

# Usage

199

wrapped_app = wrap_application(my_app)

200

```

201

202

### Custom Application Wrapper

203

204

For advanced use cases, you can create custom wrappers following the same interface:

205

206

```python

207

class CustomWrapper:

208

def __init__(self, app):

209

self.app = app

210

211

async def __call__(self, scope, receive, send, sync_spawn, call_soon):

212

# Custom application adaptation logic

213

if scope['type'] == 'http':

214

# Handle HTTP requests

215

await self.handle_http(scope, receive, send)

216

elif scope['type'] == 'websocket':

217

# Handle WebSocket connections

218

await self.handle_websocket(scope, receive, send)

219

220

async def handle_http(self, scope, receive, send):

221

# Custom HTTP handling

222

pass

223

224

async def handle_websocket(self, scope, receive, send):

225

# Custom WebSocket handling

226

pass

227

```

228

229

### Error Handling

230

231

```python

232

from hypercorn.app_wrappers import InvalidPathError, WSGIWrapper

233

234

try:

235

wrapper = WSGIWrapper(invalid_app, 1024*1024)

236

except InvalidPathError as e:

237

print(f"Failed to wrap application: {e}")

238

# Handle invalid application path

239

```

240

241

The application wrappers provide the essential bridge between standard Python web frameworks (ASGI/WSGI) and Hypercorn's high-performance async server architecture, enabling seamless integration of existing applications with modern protocol support.