or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

case-insensitive.mdimmutable-proxies.mdindex.mdmutable-multidict.mdstring-types-utilities.md

case-insensitive.mddocs/

0

# Case-Insensitive Multidict

1

2

The `CIMultiDict` class provides case-insensitive multidict functionality, ideal for HTTP headers, environment variables, and other scenarios where key casing should be ignored. It inherits all functionality from `MultiDict` while treating keys case-insensitively.

3

4

## Capabilities

5

6

### Construction

7

8

Create case-insensitive multidict instances with the same initialization patterns as `MultiDict`.

9

10

```python { .api }

11

class CIMultiDict(MultiDict[_V]):

12

def __init__(self, arg: MDArg[_V] = None, /, **kwargs: _V):

13

"""

14

Create a case-insensitive mutable multidict.

15

16

Parameters:

17

- arg: Mapping, iterable of key-value pairs, or None

18

- **kwargs: Additional key-value pairs

19

20

All keys are treated case-insensitively for lookups and operations.

21

"""

22

```

23

24

Usage examples:

25

26

```python

27

# HTTP headers (case-insensitive by specification)

28

headers = CIMultiDict([

29

('Content-Type', 'text/html'),

30

('content-length', '1234'),

31

('CACHE-CONTROL', 'no-cache')

32

])

33

34

# Environment-style variables

35

env_vars = CIMultiDict({

36

'PATH': '/usr/bin',

37

'home': '/home/user'

38

})

39

40

# Mixed case initialization

41

config = CIMultiDict([('Debug', 'true')], timeout='30', MAX_SIZE='1024')

42

```

43

44

### Case-Insensitive Access

45

46

Access values using keys of any case - the original case of the first occurrence is preserved for storage.

47

48

```python { .api }

49

# All MultiDict methods work case-insensitively

50

def __getitem__(self, key: str) -> _V: ...

51

def get(self, key: str, default=None): ...

52

def getone(self, key: str, default=None): ...

53

def getall(self, key: str, default=None): ...

54

def __contains__(self, key: object) -> bool: ...

55

```

56

57

Usage examples:

58

59

```python

60

headers = CIMultiDict([

61

('Content-Type', 'text/html'),

62

('Accept-Encoding', 'gzip'),

63

('accept-encoding', 'deflate') # Second value for same key

64

])

65

66

# All these access the same key

67

print(headers['content-type']) # 'text/html'

68

print(headers['CONTENT-TYPE']) # 'text/html'

69

print(headers['Content-Type']) # 'text/html'

70

71

# Get all values case-insensitively

72

print(headers.getall('ACCEPT-ENCODING')) # ['gzip', 'deflate']

73

74

# Check existence case-insensitively

75

print('content-type' in headers) # True

76

print('CONTENT-TYPE' in headers) # True

77

```

78

79

### Case-Insensitive Modifications

80

81

All modification operations work case-insensitively while preserving the original case of the first key occurrence.

82

83

```python { .api }

84

def add(self, key: str, value: _V) -> None: ...

85

def __setitem__(self, key: str, value: _V) -> None: ...

86

def __delitem__(self, key: str) -> None: ...

87

def update(self, arg: MDArg[_V] = None, /, **kwargs: _V) -> None: ...

88

def extend(self, arg: MDArg[_V] = None, /, **kwargs: _V) -> None: ...

89

def merge(self, arg: MDArg[_V] = None, /, **kwargs: _V) -> None: ...

90

```

91

92

Usage examples:

93

94

```python

95

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

96

97

# Add to existing key (case-insensitive match)

98

headers.add('content-type', 'application/json')

99

print(headers.getall('Content-Type')) # ['text/html', 'application/json']

100

101

# Set value (replaces all, case-insensitive)

102

headers['CONTENT-TYPE'] = 'text/plain'

103

print(headers['content-type']) # 'text/plain'

104

105

# Delete case-insensitively

106

del headers['content-type']

107

print('Content-Type' in headers) # False

108

```

109

110

### Key Case Preservation

111

112

The multidict preserves the case of keys as first encountered, while treating all operations case-insensitively.

113

114

```python

115

headers = CIMultiDict()

116

117

# First occurrence sets the case

118

headers.add('Content-Type', 'text/html')

119

headers.add('content-type', 'application/json') # Same key, different case

120

121

# Original case is preserved in iteration

122

print(list(headers.keys())) # ['Content-Type', 'Content-Type']

123

124

# But access works case-insensitively

125

print(headers['CONTENT-TYPE']) # 'text/html' (first value)

126

```

127

128

### HTTP Header Patterns

129

130

Common patterns for working with HTTP headers using case-insensitive multidicts.

131

132

```python

133

# Parse HTTP headers

134

def parse_headers(header_lines):

135

headers = CIMultiDict()

136

for line in header_lines:

137

if ':' in line:

138

key, value = line.split(':', 1)

139

headers.add(key.strip(), value.strip())

140

return headers

141

142

# Common header operations

143

headers = CIMultiDict([

144

('Accept', 'text/html'),

145

('Accept', 'application/xml'),

146

('User-Agent', 'MyApp/1.0'),

147

('accept-encoding', 'gzip')

148

])

149

150

# Check for specific encodings

151

if 'accept-encoding' in headers:

152

encodings = headers.getall('Accept-Encoding') # Case-insensitive

153

if 'gzip' in encodings:

154

print("Client accepts gzip compression")

155

156

# Set security headers

157

headers['X-Frame-Options'] = 'DENY'

158

headers['x-content-type-options'] = 'nosniff' # Different case

159

160

# Both access the same data

161

print(headers['X-CONTENT-TYPE-OPTIONS']) # 'nosniff'

162

```

163

164

### Integration with Regular MultiDict

165

166

Case-insensitive multidicts can work alongside regular multidicts and convert between them.

167

168

```python { .api }

169

def copy(self) -> 'CIMultiDict[_V]':

170

"""Return a shallow copy as a CIMultiDict."""

171

```

172

173

Usage examples:

174

175

```python

176

# Convert regular multidict to case-insensitive

177

regular_md = MultiDict([('Key', 'value1'), ('key', 'value2')])

178

ci_md = CIMultiDict(regular_md) # Now case-insensitive

179

180

# Convert back to regular (preserves current key cases)

181

back_to_regular = MultiDict(ci_md)

182

183

# Copy maintains case-insensitive behavior

184

ci_copy = ci_md.copy() # Returns CIMultiDict

185

```

186

187

### Working with istr Keys

188

189

When working with case-insensitive strings directly, you can use `istr` objects.

190

191

```python

192

from multidict import CIMultiDict, istr

193

194

headers = CIMultiDict()

195

196

# Both regular strings and istr work the same way

197

headers['Content-Type'] = 'text/html'

198

headers[istr('content-type')] = 'application/json' # Replaces previous

199

200

# istr comparison is case-insensitive

201

key1 = istr('Content-Type')

202

key2 = istr('content-type')

203

print(key1 == key2) # True

204

205

# But regular string behavior is preserved in storage

206

print(str(key1)) # 'Content-Type' (original case)

207

```

208

209

### Environment Variables Pattern

210

211

Common pattern for case-insensitive environment-like configuration.

212

213

```python

214

# Environment variables (case-insensitive on Windows)

215

env = CIMultiDict([

216

('PATH', '/usr/bin:/bin'),

217

('Home', '/home/user'),

218

('PYTHONPATH', '/opt/python')

219

])

220

221

# Access regardless of case

222

print(env.get('path')) # '/usr/bin:/bin'

223

print(env.get('HOME')) # '/home/user'

224

print(env.get('pythonpath')) # '/opt/python'

225

226

# Set new variables

227

env['temp'] = '/tmp'

228

env['TEMP'] = '/var/tmp' # Replaces previous (case-insensitive)

229

230

print(env['temp']) # '/var/tmp'

231

```