๐ฏ Core functionality for the WhyML ecosystem - validation, loading, processing, and manifest manipulation
WhyML Core provides the foundational infrastructure for the WhyML ecosystem, offering robust tools for YAML manifest processing, template inheritance, dependency resolution, and async operations. Built with modern Python patterns and comprehensive error handling.
โ EXCEPTION SYSTEM: Enhanced exception classes with improved constructors:
details parameter for comprehensive error contextโ
VALIDATION FRAMEWORK: Added ValidationResult class to whyml-core validation module for structured validation reporting and compatibility with existing test suites.
โ
LOADEDMANIFEST HANDLING: Improved LoadedManifest dataclass structure with proper .content attribute extraction patterns throughout the ecosystem.
โ BACKWARDS COMPATIBILITY: Maintained full backwards compatibility while adding new functionality and fixing critical CLI conversion issues.
<?=VAR?>)pip install whyml-core
For development dependencies:
pip install whyml-core[dev]
WhyML Core is organized into focused modules:
exceptions/ - Comprehensive exception hierarchyvalidation/ - Manifest validation with schema supportloading/ - Async manifest loading and dependency managementprocessing/ - Template processing and inheritance resolutionutils/ - Utility functions for common operationswhyml_core/
โโโ exceptions/ # Exception handling
โ โโโ base_exceptions.py # Base exception classes
โ โโโ validation_exceptions.py # Validation-specific exceptions
โ โโโ processing_exceptions.py # Processing-specific exceptions
โโโ validation/ # Validation framework
โ โโโ manifest_validator.py # Core manifest validation
โ โโโ schema_loader.py # JSON schema management
โ โโโ field_validators.py # Specialized field validators
โโโ loading/ # Loading and dependency management
โ โโโ manifest_loader.py # Async manifest loading
โ โโโ cache_manager.py # Advanced caching system
โ โโโ dependency_resolver.py # Dependency graph resolution
โโโ processing/ # Template processing
โ โโโ template_processor.py # Jinja2 template engine
โ โโโ inheritance_resolver.py # Template inheritance
โ โโโ variable_substitution.py # Variable substitution
โโโ utils/ # Utilities
โโโ yaml_utils.py # YAML processing utilities
โโโ async_utils.py # Async operation helpers
โโโ path_utils.py # Path manipulation
โโโ string_utils.py # String processing
from whyml_core.validation import ManifestValidator
validator = ManifestValidator()
# Validate a manifest
manifest = {
'metadata': {'title': 'My App', 'version': '1.0.0'},
'structure': {'body': {'content': 'Hello World'}}
}
try:
is_valid = await validator.validate_manifest(manifest)
print(f"Manifest is valid: {is_valid}")
except ValidationError as e:
print(f"Validation error: {e.message}")
from whyml_core.loading import ManifestLoader
loader = ManifestLoader()
# Load manifest with dependencies
async def load_example():
manifest = await loader.load_manifest('manifest.yaml')
return manifest
# With dependency resolution
manifest = await loader.load_with_dependencies('main-manifest.yaml')
from whyml_core.processing import TemplateProcessor
processor = TemplateProcessor()
# Process templates with variables
template_vars = {
'app_name': 'MyApp',
'version': '1.0.0'
}
processed = processor.substitute_template_variables(
'Welcome to v',
template_vars
)
from whyml_core import (
ManifestLoader,
ManifestValidator,
TemplateProcessor,
InheritanceResolver
)
async def process_manifest(manifest_path: str):
# Load manifest
loader = ManifestLoader()
manifest = await loader.load_manifest(manifest_path)
# Validate
validator = ManifestValidator()
await validator.validate_manifest(manifest)
# Process inheritance
resolver = InheritanceResolver()
resolved = await resolver.resolve_inheritance(manifest)
# Process templates
processor = TemplateProcessor()
final_manifest = processor.substitute_template_vars(resolved)
return final_manifest
from whyml_core.validation import SchemaLoader
schema_loader = SchemaLoader()
# Load custom schema
custom_schema = await schema_loader.load_schema('custom-schema.json')
# Use with validator
validator = ManifestValidator(schema_loader=schema_loader)
from whyml_core.loading import CacheManager
# Configure caching
cache_manager = CacheManager(max_size=1000, ttl=3600)
# Use with loader
loader = ManifestLoader(cache_manager=cache_manager)
from whyml_core.utils import AsyncFileManager
async def example():
file_manager = AsyncFileManager()
# Read file with caching
content = await file_manager.read_file('data.yaml')
# Write file with directory creation
await file_manager.write_file('output/result.yaml', content)
from whyml_core.utils import YAMLUtils, YAMLProcessor
# Basic operations
data = YAMLUtils.load_file('manifest.yaml')
YAMLUtils.save_file(data, 'output.yaml')
# Advanced processing
processor = YAMLProcessor()
normalized = processor.normalize_manifest(manifest)
excerpt = processor.extract_sections(manifest, ['metadata', 'structure'])
WhyML Core provides comprehensive error handling:
from whyml_core.exceptions import (
WhyMLError,
ValidationError,
TemplateError,
ManifestError
)
try:
result = await some_operation()
except ValidationError as e:
print(f"Validation failed: {e.message}")
print(f"Details: {e.details}")
except TemplateError as e:
print(f"Template processing error: {e.message}")
print(f"Context: {e.context}")
except WhyMLError as e:
# Base class catches all WhyML-specific errors
print(f"WhyML error: {e}")
Run the test suite:
# Install test dependencies
pip install whyml-core[test]
# Run tests
pytest
# Run with coverage
pytest --cov=whyml_core --cov-report=html
WhyML Core is part of the larger WhyML ecosystem. Contributions are welcome!
WhyML Core is designed to work with other WhyML packages:
Licensed under the Apache License, Version 2.0. See LICENSE for details.
WhyML Core - Empowering modular manifest processing with robust, async-first architecture.