Python lib/cli for JSON/YAML schema validation
—
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.
yml: ruamel.yaml.YAML # Global YAML loader/dumper instancebasestring: type # Base string type (str in Python 3, basestring in Python 2)
unicode: type # Unicode string type (str in Python 3, unicode in Python 2)
bytes: type # Bytes type (consistent across versions)def u(x):
"""
Convert string to unicode.
Args:
x (str): String to convert
Returns:
str: Unicode string (Python 3) or unicode (Python 2)
"""
def b(x):
"""
Convert string to bytes.
Args:
x (str): String to convert
Returns:
bytes: Byte string
"""
def nativestr(x):
"""
Convert to native string type for the current Python version.
Args:
x: Object to convert
Returns:
str: Native string representation
"""from pykwalify.compat import yml
# Load YAML content (works across ruamel.yaml versions)
yaml_content = """
name: Test
values:
- item1
- item2
"""
data = yml.load(yaml_content)
print(f"Loaded data: {data}")
# Save YAML content
import io
output = io.StringIO()
yml.dump(data, output)
print(f"YAML output: {output.getvalue()}")from pykwalify.compat import basestring, unicode, u, b, nativestr
# Check if value is any string type (works in Python 2 and 3)
def is_string_like(value):
return isinstance(value, basestring)
# Examples
test_values = ["hello", u"unicode", b"bytes"]
for value in test_values:
print(f"'{value}' is string-like: {is_string_like(value)}")
# String conversion utilities
text = "Hello, World!"
unicode_text = u(text) # Ensure unicode
byte_text = b(text) # Convert to bytes
native_text = nativestr(text) # Native string type
print(f"Original: {text}")
print(f"Unicode: {unicode_text}")
print(f"Bytes: {byte_text}")
print(f"Native: {native_text}")from pykwalify.compat import basestring, unicode
def validate_string_input(value):
"""Validate string input that works across Python versions."""
if not isinstance(value, basestring):
raise TypeError(f"Expected string, got {type(value)}")
# Convert to unicode for consistent processing
if not isinstance(value, unicode):
value = value.decode('utf-8')
return value
# Test with different string types
test_strings = ["ascii", u"unicode", "utf-8 text"]
for s in test_strings:
try:
result = validate_string_input(s)
print(f"Validated: {result}")
except Exception as e:
print(f"Error: {e}")from pykwalify.core import Core
from pykwalify.compat import yml
import io
# Create YAML content programmatically using compatible YAML handler
schema_dict = {
"type": "map",
"mapping": {
"name": {"type": "str", "required": True},
"version": {"type": "str"}
}
}
data_dict = {
"name": "MyProject",
"version": "1.0.0"
}
# Convert to YAML strings using compatibility layer
schema_stream = io.StringIO()
data_stream = io.StringIO()
yml.dump(schema_dict, schema_stream)
yml.dump(data_dict, data_stream)
schema_yaml = schema_stream.getvalue()
data_yaml = data_stream.getvalue()
print("Generated schema:")
print(schema_yaml)
print("Generated data:")
print(data_yaml)
# Use with Core validation
c = Core(source_data=data_dict, schema_data=schema_dict)
try:
c.validate(raise_exception=True)
print("Validation successful with compatibility layer!")
except Exception as e:
print(f"Validation failed: {e}")from pykwalify.compat import yml
# The yml object is a configured ruamel.yaml.YAML instance
# You can access its properties and methods
# Configure YAML processing
yml.width = 4096 # Set line width
yml.preserve_quotes = True # Preserve quotes in output
# Load with custom handling
def load_yaml_safely(content):
"""Load YAML with error handling."""
try:
return yml.load(content)
except Exception as e:
print(f"YAML loading failed: {e}")
return None
# Test YAML loading
yaml_content = '''
# Configuration file
app:
name: "MyApp"
debug: true
features:
- feature1
- feature2
'''
config = load_yaml_safely(yaml_content)
if config:
print(f"Loaded config: {config}")from pykwalify.compat import basestring, unicode, nativestr
from pykwalify.errors import CoreError
def safe_string_conversion(value, target_type="unicode"):
"""Safely convert strings with proper error handling."""
try:
if target_type == "unicode":
if isinstance(value, unicode):
return value
elif isinstance(value, bytes):
return value.decode('utf-8')
else:
return unicode(str(value))
elif target_type == "native":
return nativestr(value)
else:
raise ValueError(f"Unknown target type: {target_type}")
except UnicodeDecodeError as e:
raise CoreError(f"String encoding error: {e}")
except Exception as e:
raise CoreError(f"String conversion error: {e}")
# Test conversion
test_values = ["ascii", u"unicode", b"bytes", 123, None]
for value in test_values:
try:
result = safe_string_conversion(value)
print(f"Converted '{value}' -> '{result}' (type: {type(result)})")
except Exception as e:
print(f"Failed to convert '{value}': {e}")The compatibility layer handles the following version differences:
basestring and unicode typesruamel.yaml for consistent YAML 1.2 supportThis 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.
Install with Tessl CLI
npx tessl i tessl/pypi-pykwalify