0
# Compatibility Layer
1
2
PyKwalify provides cross-version compatibility utilities to ensure consistent behavior across Python 2/3 and different YAML library versions. The compatibility layer abstracts differences between Python versions and provides unified interfaces for string handling and YAML processing.
3
4
## Capabilities
5
6
### YAML Processing
7
8
```python { .api }
9
yml: ruamel.yaml.YAML # Global YAML loader/dumper instance
10
```
11
12
### String Type Compatibility
13
14
```python { .api }
15
basestring: type # Base string type (str in Python 3, basestring in Python 2)
16
unicode: type # Unicode string type (str in Python 3, unicode in Python 2)
17
bytes: type # Bytes type (consistent across versions)
18
```
19
20
### String Conversion Utilities
21
22
```python { .api }
23
def u(x):
24
"""
25
Convert string to unicode.
26
27
Args:
28
x (str): String to convert
29
30
Returns:
31
str: Unicode string (Python 3) or unicode (Python 2)
32
"""
33
34
def b(x):
35
"""
36
Convert string to bytes.
37
38
Args:
39
x (str): String to convert
40
41
Returns:
42
bytes: Byte string
43
"""
44
45
def nativestr(x):
46
"""
47
Convert to native string type for the current Python version.
48
49
Args:
50
x: Object to convert
51
52
Returns:
53
str: Native string representation
54
"""
55
```
56
57
## Usage Examples
58
59
### YAML Processing
60
61
```python
62
from pykwalify.compat import yml
63
64
# Load YAML content (works across ruamel.yaml versions)
65
yaml_content = """
66
name: Test
67
values:
68
- item1
69
- item2
70
"""
71
72
data = yml.load(yaml_content)
73
print(f"Loaded data: {data}")
74
75
# Save YAML content
76
import io
77
output = io.StringIO()
78
yml.dump(data, output)
79
print(f"YAML output: {output.getvalue()}")
80
```
81
82
### Cross-Version String Handling
83
84
```python
85
from pykwalify.compat import basestring, unicode, u, b, nativestr
86
87
# Check if value is any string type (works in Python 2 and 3)
88
def is_string_like(value):
89
return isinstance(value, basestring)
90
91
# Examples
92
test_values = ["hello", u"unicode", b"bytes"]
93
for value in test_values:
94
print(f"'{value}' is string-like: {is_string_like(value)}")
95
96
# String conversion utilities
97
text = "Hello, World!"
98
unicode_text = u(text) # Ensure unicode
99
byte_text = b(text) # Convert to bytes
100
native_text = nativestr(text) # Native string type
101
102
print(f"Original: {text}")
103
print(f"Unicode: {unicode_text}")
104
print(f"Bytes: {byte_text}")
105
print(f"Native: {native_text}")
106
```
107
108
### Type Checking Across Versions
109
110
```python
111
from pykwalify.compat import basestring, unicode
112
113
def validate_string_input(value):
114
"""Validate string input that works across Python versions."""
115
if not isinstance(value, basestring):
116
raise TypeError(f"Expected string, got {type(value)}")
117
118
# Convert to unicode for consistent processing
119
if not isinstance(value, unicode):
120
value = value.decode('utf-8')
121
122
return value
123
124
# Test with different string types
125
test_strings = ["ascii", u"unicode", "utf-8 text"]
126
for s in test_strings:
127
try:
128
result = validate_string_input(s)
129
print(f"Validated: {result}")
130
except Exception as e:
131
print(f"Error: {e}")
132
```
133
134
### Integration with Core Validation
135
136
```python
137
from pykwalify.core import Core
138
from pykwalify.compat import yml
139
import io
140
141
# Create YAML content programmatically using compatible YAML handler
142
schema_dict = {
143
"type": "map",
144
"mapping": {
145
"name": {"type": "str", "required": True},
146
"version": {"type": "str"}
147
}
148
}
149
150
data_dict = {
151
"name": "MyProject",
152
"version": "1.0.0"
153
}
154
155
# Convert to YAML strings using compatibility layer
156
schema_stream = io.StringIO()
157
data_stream = io.StringIO()
158
159
yml.dump(schema_dict, schema_stream)
160
yml.dump(data_dict, data_stream)
161
162
schema_yaml = schema_stream.getvalue()
163
data_yaml = data_stream.getvalue()
164
165
print("Generated schema:")
166
print(schema_yaml)
167
print("Generated data:")
168
print(data_yaml)
169
170
# Use with Core validation
171
c = Core(source_data=data_dict, schema_data=schema_dict)
172
try:
173
c.validate(raise_exception=True)
174
print("Validation successful with compatibility layer!")
175
except Exception as e:
176
print(f"Validation failed: {e}")
177
```
178
179
## Advanced Usage
180
181
### Custom YAML Processing
182
183
```python
184
from pykwalify.compat import yml
185
186
# The yml object is a configured ruamel.yaml.YAML instance
187
# You can access its properties and methods
188
189
# Configure YAML processing
190
yml.width = 4096 # Set line width
191
yml.preserve_quotes = True # Preserve quotes in output
192
193
# Load with custom handling
194
def load_yaml_safely(content):
195
"""Load YAML with error handling."""
196
try:
197
return yml.load(content)
198
except Exception as e:
199
print(f"YAML loading failed: {e}")
200
return None
201
202
# Test YAML loading
203
yaml_content = '''
204
# Configuration file
205
app:
206
name: "MyApp"
207
debug: true
208
features:
209
- feature1
210
- feature2
211
'''
212
213
config = load_yaml_safely(yaml_content)
214
if config:
215
print(f"Loaded config: {config}")
216
```
217
218
### Error Handling in Compatibility Context
219
220
```python
221
from pykwalify.compat import basestring, unicode, nativestr
222
from pykwalify.errors import CoreError
223
224
def safe_string_conversion(value, target_type="unicode"):
225
"""Safely convert strings with proper error handling."""
226
try:
227
if target_type == "unicode":
228
if isinstance(value, unicode):
229
return value
230
elif isinstance(value, bytes):
231
return value.decode('utf-8')
232
else:
233
return unicode(str(value))
234
235
elif target_type == "native":
236
return nativestr(value)
237
238
else:
239
raise ValueError(f"Unknown target type: {target_type}")
240
241
except UnicodeDecodeError as e:
242
raise CoreError(f"String encoding error: {e}")
243
except Exception as e:
244
raise CoreError(f"String conversion error: {e}")
245
246
# Test conversion
247
test_values = ["ascii", u"unicode", b"bytes", 123, None]
248
for value in test_values:
249
try:
250
result = safe_string_conversion(value)
251
print(f"Converted '{value}' -> '{result}' (type: {type(result)})")
252
except Exception as e:
253
print(f"Failed to convert '{value}': {e}")
254
```
255
256
## Internal Implementation Notes
257
258
The compatibility layer handles the following version differences:
259
260
- **Python 2/3 String Types**: Provides unified `basestring` and `unicode` types
261
- **YAML Library**: Uses `ruamel.yaml` for consistent YAML 1.2 support
262
- **Encoding Handling**: Provides utilities for safe string encoding/decoding
263
- **Type Checking**: Ensures isinstance() checks work across versions
264
265
This layer is primarily used internally by PyKwalify but is exposed for advanced users who need cross-version compatibility in their validation extensions or custom code.