0
# String and Bytes Utilities
1
2
Utilities for handling string and bytes data consistently across Python versions. These functions provide unified interfaces for text/binary data operations, literal creation, encoding/decoding, and type coercion that work identically on Python 2 and 3.
3
4
## Capabilities
5
6
### Literal Creation Functions
7
8
Functions for creating string and byte literals that work consistently across Python versions.
9
10
```python { .api }
11
def b(s: str) -> bytes
12
"""Create byte literal from string in a cross-version way."""
13
14
def u(s: str) -> str
15
"""Create text literal from string in a cross-version way."""
16
```
17
18
**Usage Examples:**
19
20
```python
21
import six
22
23
# Create byte literals
24
byte_data = six.b("hello world") # Returns bytes on both PY2 and PY3
25
text_data = six.u("hello world") # Returns text/unicode on both PY2 and PY3
26
27
# Use in protocol or file operations
28
with open("data.bin", "wb") as f:
29
f.write(six.b("binary data"))
30
31
# Use in text processing
32
message = six.u("Unicode message: ∑αμπλε")
33
```
34
35
### Unicode Character Function
36
37
Function for creating unicode characters from code points.
38
39
```python { .api }
40
def unichr(i: int) -> str
41
"""Return unicode character for given code point."""
42
```
43
44
**Usage Example:**
45
46
```python
47
import six
48
49
# Create unicode characters
50
heart = six.unichr(0x2665) # ♥
51
euro = six.unichr(0x20AC) # €
52
```
53
54
### Byte/Integer Conversion
55
56
Functions for converting between bytes and integers across Python versions.
57
58
```python { .api }
59
def int2byte(i: int) -> bytes
60
"""Convert integer (0-255) to single byte."""
61
62
def byte2int(bs: bytes) -> int
63
"""Convert single byte to integer."""
64
65
def indexbytes(buf: bytes, i: int) -> int
66
"""Index into bytes returning an integer."""
67
68
def iterbytes(buf: bytes) -> Iterator[int]
69
"""Iterate over bytes as integers."""
70
```
71
72
**Usage Examples:**
73
74
```python
75
import six
76
77
# Convert integer to byte
78
byte_val = six.int2byte(65) # b'A'
79
80
# Convert byte to integer
81
int_val = six.byte2int(b'A') # 65
82
83
# Index into bytes (returns int in PY3, str in PY2)
84
data = b"hello"
85
first_byte_as_int = six.indexbytes(data, 0) # Always returns int
86
87
# Iterate over bytes as integers
88
for byte_val in six.iterbytes(b"hello"):
89
print(byte_val) # Prints: 104, 101, 108, 108, 111
90
```
91
92
### Type Coercion Functions
93
94
Functions that ensure data is in the correct string/bytes format across Python versions.
95
96
```python { .api }
97
def ensure_binary(s: str | bytes, encoding: str = 'utf-8', errors: str = 'strict') -> bytes
98
"""Coerce **s** to bytes."""
99
100
def ensure_str(s: str | bytes, encoding: str = 'utf-8', errors: str = 'strict') -> str
101
"""Coerce **s** to str."""
102
103
def ensure_text(s: str | bytes, encoding: str = 'utf-8', errors: str = 'strict') -> str
104
"""Coerce **s** to text (unicode in PY2, str in PY3)."""
105
```
106
107
**Parameters:**
108
- `s`: String or bytes data to coerce
109
- `encoding`: Text encoding to use for conversion (default: 'utf-8')
110
- `errors`: Error handling strategy ('strict', 'ignore', 'replace', etc.)
111
112
**Usage Examples:**
113
114
```python
115
import six
116
117
# Ensure binary data
118
text_input = "hello world"
119
byte_input = b"hello world"
120
both_binary = [six.ensure_binary(text_input), six.ensure_binary(byte_input)]
121
# Both return b"hello world"
122
123
# Ensure str type (native string for each Python version)
124
text_str = six.ensure_str("hello") # Returns str
125
bytes_str = six.ensure_str(b"hello") # Returns str (decoded)
126
127
# Ensure text type (unicode in PY2, str in PY3)
128
text_unicode = six.ensure_text("hello") # Returns unicode/str
129
bytes_unicode = six.ensure_text(b"hello") # Returns unicode/str (decoded)
130
131
# With custom encoding
132
latin1_data = b"\xe9\xe8\xe7"
133
text = six.ensure_text(latin1_data, encoding='latin-1')
134
```
135
136
### IO Classes
137
138
Cross-version IO classes for string and bytes operations.
139
140
```python { .api }
141
StringIO: type # String-based IO class
142
BytesIO: type # Bytes-based IO class
143
```
144
145
These provide the appropriate IO classes for string and bytes operations:
146
- `StringIO`: `io.StringIO` in Python 3, `StringIO.StringIO` in Python 2
147
- `BytesIO`: `io.BytesIO` in both versions
148
149
**Usage Examples:**
150
151
```python
152
import six
153
154
# String IO operations
155
string_buffer = six.StringIO()
156
string_buffer.write(six.u("Hello, world!"))
157
content = string_buffer.getvalue()
158
159
# Bytes IO operations
160
bytes_buffer = six.BytesIO()
161
bytes_buffer.write(six.b("Hello, world!"))
162
binary_content = bytes_buffer.getvalue()
163
164
# Use in functions expecting file-like objects
165
def process_text_data(file_obj):
166
return file_obj.read().upper()
167
168
result = process_text_data(six.StringIO(six.u("hello")))
169
```
170
171
### Unicode Compatibility Decorator
172
173
Class decorator for Python 2 unicode compatibility.
174
175
```python { .api }
176
def python_2_unicode_compatible(cls: type) -> type
177
"""Class decorator for unicode compatibility in Python 2."""
178
```
179
180
This decorator allows classes to define `__str__` methods that return unicode strings in Python 2 and regular strings in Python 3, ensuring consistent string representation behavior.
181
182
**Usage Example:**
183
184
```python
185
import six
186
187
@six.python_2_unicode_compatible
188
class Person:
189
def __init__(self, name):
190
self.name = name
191
192
def __str__(self):
193
return "Person: {}".format(self.name)
194
195
# Works consistently across Python versions
196
person = Person("José")
197
print(str(person)) # Handles unicode correctly in both PY2 and PY3
198
```
199
200
## Method/Function Attribute Constants
201
202
String constants for accessing function and method attributes across Python versions.
203
204
```python { .api }
205
_meth_func: str # Method function attribute name
206
_meth_self: str # Method self attribute name
207
_func_closure: str # Function closure attribute name
208
_func_code: str # Function code attribute name
209
_func_defaults: str # Function defaults attribute name
210
_func_globals: str # Function globals attribute name
211
```
212
213
These constants provide the correct attribute names for introspection:
214
215
**Usage Example:**
216
217
```python
218
import six
219
220
def example_function(a, b=10):
221
return a + b
222
223
# Access function attributes cross-version
224
closure = getattr(example_function, six._func_closure)
225
defaults = getattr(example_function, six._func_defaults) # (10,)
226
code = getattr(example_function, six._func_code)
227
globals_dict = getattr(example_function, six._func_globals)
228
```
229
230
## Common Usage Patterns
231
232
```python
233
import six
234
235
# Protocol handling with consistent types
236
def handle_data(data):
237
# Ensure we have bytes for binary protocols
238
binary_data = six.ensure_binary(data)
239
240
# Process binary data
241
processed = process_binary(binary_data)
242
243
# Return as text for display
244
return six.ensure_text(processed)
245
246
# File handling with proper encoding
247
def read_config_file(filename):
248
with open(filename, 'rb') as f:
249
raw_data = f.read()
250
251
# Convert to text with proper encoding
252
text_data = six.ensure_text(raw_data, encoding='utf-8')
253
return text_data.split('\n')
254
255
# Cross-version string buffer usage
256
def build_response():
257
buffer = six.StringIO()
258
buffer.write(six.u("HTTP/1.1 200 OK\r\n"))
259
buffer.write(six.u("Content-Type: text/plain\r\n"))
260
buffer.write(six.u("\r\n"))
261
buffer.write(six.u("Hello, World!"))
262
return buffer.getvalue()
263
```