Python lib/cli for JSON/YAML schema validation
—
PyKwalify provides CLI functionality for validating YAML/JSON files from the command line with support for extensions, encoding options, and various validation flags.
def parse_cli():
"""
Parse command line arguments using docopt.
Returns:
dict: Parsed command line arguments
"""
def run(cli_args):
"""
Execute validation with parsed CLI arguments.
Args:
cli_args (dict): Parsed command line arguments from parse_cli()
Returns:
int: Exit code (0 for success, non-zero for errors)
"""
def cli_entrypoint():
"""
Main CLI entry point function.
Called when 'pykwalify' command is executed.
"""pykwalify -d FILE -s FILE ... [-e FILE ...]
[--strict-rule-validation] [--fix-ruby-style-regex] [--allow-assertions]
[--encoding ENCODING] [-v ...] [-q]-d FILE, --data-file FILE # The file to be validated
-s FILE, --schema-file FILE # Schema definition file (can be specified multiple times)-e FILE, --extension FILE # Python extension file (can be specified multiple times)
-h, --help # Show help message and exit
-q, --quiet # Suppress terminal output
-v, --verbose # Verbose terminal output (multiple -v increases verbosity)
--version # Display version number and exit--strict-rule-validation # Enable strict validation of all keywords for Rule objects
--fix-ruby-style-regex # Fix Ruby-style regex compatibility issues
--allow-assertions # Enable assertion keyword (disabled by default for security)
--encoding ENCODING # Specify encoding to open data and schema files# Validate a YAML file against a schema
pykwalify -d data.yaml -s schema.yaml
# Validate a JSON file against a schema
pykwalify -d data.json -s schema.yaml
# Multiple schema files
pykwalify -d data.yaml -s base_schema.yaml -s extended_schema.yaml# Strict validation with verbose output
pykwalify -d data.yaml -s schema.yaml --strict-rule-validation -vv
# With custom encoding
pykwalify -d data.yaml -s schema.yaml --encoding utf-16
# Enable assertions (use with caution)
pykwalify -d data.yaml -s schema.yaml --allow-assertions
# Fix Ruby regex compatibility
pykwalify -d data.yaml -s schema.yaml --fix-ruby-style-regex# Load custom validation functions
pykwalify -d data.yaml -s schema.yaml -e custom_validators.py
# Multiple extension files
pykwalify -d data.yaml -s schema.yaml -e validators1.py -e validators2.py# Quiet mode (suppress output)
pykwalify -d data.yaml -s schema.yaml -q
# Verbose output (single level)
pykwalify -d data.yaml -s schema.yaml -v
# Very verbose output (multiple levels)
pykwalify -d data.yaml -s schema.yaml -vvv# Show version
pykwalify --version
# Show help
pykwalify --help
pykwalify -hThe CLI uses specific exit codes to indicate different types of errors:
# Exit codes
0 # Success - no errors
1 # Unknown error
2 # Schema error - validation failure
3 # Core error - processing error
4 # Rule error - rule processing error
5 # Schema conflict - conflicting schema definitions
6 # Not mapping error - expected dict but got different type
7 # Not sequence error - expected list but got different type#!/bin/bash
DATA_FILE="config.yaml"
SCHEMA_FILE="config_schema.yaml"
echo "Validating $DATA_FILE against $SCHEMA_FILE..."
if pykwalify -d "$DATA_FILE" -s "$SCHEMA_FILE" -q; then
echo "✓ Validation successful"
exit 0
else
echo "✗ Validation failed"
exit 1
fivalidate:
@echo "Validating configuration files..."
@pykwalify -d config/app.yaml -s schemas/app_schema.yaml
@pykwalify -d config/db.yaml -s schemas/db_schema.yaml
@echo "All validations passed!"
validate-verbose:
pykwalify -d config/app.yaml -s schemas/app_schema.yaml -vv
pykwalify -d config/db.yaml -s schemas/db_schema.yaml -vv
.PHONY: validate validate-verbose# GitHub Actions example
- name: Validate YAML files
run: |
pip install pykwalify
pykwalify -d .github/workflows/ci.yml -s schemas/github_workflow_schema.yaml
pykwalify -d config/production.yaml -s schemas/config_schema.yaml
# GitLab CI example
validate_configs:
script:
- pip install pykwalify
- pykwalify -d config.yaml -s schema.yaml --strict-rule-validation
only:
changes:
- "*.yaml"
- "*.yml"#!/bin/bash
# Validate multiple files with the same schema
SCHEMA="schemas/api_schema.yaml"
EXIT_CODE=0
for file in data/*.yaml; do
echo "Validating $file..."
if ! pykwalify -d "$file" -s "$SCHEMA" -q; then
echo "❌ $file failed validation"
EXIT_CODE=1
else
echo "✅ $file passed validation"
fi
done
if [ $EXIT_CODE -eq 0 ]; then
echo "All files validated successfully!"
else
echo "Some files failed validation"
fi
exit $EXIT_CODE#!/bin/bash
validate_file() {
local data_file=$1
local schema_file=$2
# Capture both exit code and output
local output
output=$(pykwalify -d "$data_file" -s "$schema_file" 2>&1)
local exit_code=$?
case $exit_code in
0)
echo "✓ $data_file: Valid"
return 0
;;
2)
echo "✗ $data_file: Schema validation failed"
echo " Details: $output"
return 2
;;
3)
echo "✗ $data_file: Core processing error"
echo " Details: $output"
return 3
;;
*)
echo "✗ $data_file: Unknown error (code: $exit_code)"
echo " Details: $output"
return $exit_code
;;
esac
}
# Usage
validate_file "user_data.yaml" "user_schema.yaml"
validation_result=$?
if [ $validation_result -eq 0 ]; then
echo "Proceeding with deployment..."
else
echo "Aborting deployment due to validation errors"
exit $validation_result
fiCreate a custom validator file (custom_validators.py):
# custom_validators.py
def validate_custom_id(value):
"""Custom validation function for special ID format."""
if not isinstance(value, str):
return False
# Check if it matches pattern: PREFIX-YYYYMMDD-NNNN
import re
pattern = r'^[A-Z]{2,4}-\d{8}-\d{4}$'
return bool(re.match(pattern, value))Schema using the custom validator:
# schema.yaml
type: map
mapping:
id:
type: str
func: validate_custom_id
name:
type: str
required: trueCommand to use custom validator:
pykwalify -d data.yaml -s schema.yaml -e custom_validators.py# Force UTF-8 encoding for all operations
export PYTHONIOENCODING=UTF-8
pykwalify -d data.yaml -s schema.yaml# Enable detailed debugging output
export PYKWALIFY_DEBUG=true
pykwalify -d data.yaml -s schema.yaml -vv# Use organized schema directory structure
schemas/
├── common/
│ ├── base.yaml
│ └── types.yaml
├── api/
│ ├── request.yaml
│ └── response.yaml
└── config/
├── app.yaml
└── database.yaml
# Validate with multiple schemas
pykwalify -d config.yaml -s schemas/common/base.yaml -s schemas/config/app.yaml# Pre-commit hook example
#!/bin/sh
# .git/hooks/pre-commit
echo "Running YAML validation..."
find . -name "*.yaml" -o -name "*.yml" | while read file; do
if [[ $file == *"schema"* ]]; then
continue # Skip schema files
fi
schema_file="schemas/$(basename "$file" .yaml)_schema.yaml"
if [ -f "$schema_file" ]; then
pykwalify -d "$file" -s "$schema_file" -q || exit 1
fi
done
echo "✓ All YAML files validated successfully"# For large files, use appropriate verbosity
pykwalify -d large_file.yaml -s schema.yaml -q # Fastest
# For debugging, use verbose output
pykwalify -d problem_file.yaml -s schema.yaml -vv # Most detailedInstall with Tessl CLI
npx tessl i tessl/pypi-pykwalify