def __init__(self, collector=None, processors=None, validator_class=None): '''Initialise session. *collector* is used to collect schemas for use in the session and should conform to the :py:class:`~harmony.schema.collector.Collector` interface. Defaults to a :py:class:`~harmony.schema.collector.FileSystemCollector` using the environment variable :envvar:`HARMONY_SCHEMA_PATH` to discover schemas. *processors* specifies a list of :py:class:`~harmony.schema.processor.Processor` instances that will post-process any discovered schemas. If not specified will default to [:py:class:`~harmony.schema.processor.ValidateProcessor`, :py:class:`~harmony.schema.processor.MixinProcessor`]. *validator_class* should be the class to use for validation of schemas and instances. Defaults to :py:class:`harmony.schema.validator.Validator`. ''' self.schemas = Collection() self.collector = collector if self.collector is None: paths = os.environ.get('HARMONY_SCHEMA_PATH', self.DEFAULT_SCHEMA_PATH).split(os.pathsep) self.collector = FilesystemCollector(paths) self.validator_class = validator_class if self.validator_class is None: self.validator_class = Validator self.processors = processors if self.processors is None: self.processors = [ ValidateProcessor(self.validator_class), MixinProcessor() ] self.refresh()
def __init__(self, collector=None, processors=None, validator_class=None): '''Initialise session. *collector* is used to collect schemas for use in the session and should conform to the :py:class:`~harmony.schema.collector.Collector` interface. Defaults to a :py:class:`~harmony.schema.collector.FileSystemCollector` using the environment variable :envvar:`HARMONY_SCHEMA_PATH` to discover schemas. *processors* specifies a list of :py:class:`~harmony.schema.processor.Processor` instances that will post-process any discovered schemas. If not specified will default to [:py:class:`~harmony.schema.processor.ValidateProcessor`, :py:class:`~harmony.schema.processor.MixinProcessor`]. *validator_class* should be the class to use for validation of schemas and instances. Defaults to :py:class:`harmony.schema.validator.Validator`. ''' self.schemas = Collection() self.collector = collector if self.collector is None: paths = os.environ.get( 'HARMONY_SCHEMA_PATH', self.DEFAULT_SCHEMA_PATH ).split(os.pathsep) self.collector = FilesystemCollector(paths) self.validator_class = validator_class if self.validator_class is None: self.validator_class = Validator self.processors = processors if self.processors is None: self.processors = [ ValidateProcessor(self.validator_class), MixinProcessor() ] self.refresh()
class Session(object): '''A configuration of the various components in a standard way.''' #: The default schema search path. DEFAULT_SCHEMA_PATH = os.path.join( os.path.dirname(__file__), '..', '..', 'resource', 'schema' ) def __init__(self, collector=None, processors=None, validator_class=None): '''Initialise session. *collector* is used to collect schemas for use in the session and should conform to the :py:class:`~harmony.schema.collector.Collector` interface. Defaults to a :py:class:`~harmony.schema.collector.FileSystemCollector` using the environment variable :envvar:`HARMONY_SCHEMA_PATH` to discover schemas. *processors* specifies a list of :py:class:`~harmony.schema.processor.Processor` instances that will post-process any discovered schemas. If not specified will default to [:py:class:`~harmony.schema.processor.ValidateProcessor`, :py:class:`~harmony.schema.processor.MixinProcessor`]. *validator_class* should be the class to use for validation of schemas and instances. Defaults to :py:class:`harmony.schema.validator.Validator`. ''' self.schemas = Collection() self.collector = collector if self.collector is None: paths = os.environ.get( 'HARMONY_SCHEMA_PATH', self.DEFAULT_SCHEMA_PATH ).split(os.pathsep) self.collector = FilesystemCollector(paths) self.validator_class = validator_class if self.validator_class is None: self.validator_class = Validator self.processors = processors if self.processors is None: self.processors = [ ValidateProcessor(self.validator_class), MixinProcessor() ] self.refresh() def refresh(self): '''Discover schemas and add to local collection. .. note:: Collection will be processed with self.processors. ''' self.schemas.clear() for schema in self.collector.collect(): self.schemas.add(schema) for processor in self.processors: processor.process(self.schemas) def instantiate(self, schema, data=None): '''Instantiate *schema* with initial *data*. *schema* may be either a registered schema id or a schema object. Only required properties with default values will be used from the schema to construct the instance. Any values in *data* will take precedence over those in the schema. ''' if isinstance(schema, basestring): schema = self.schemas.get(schema) if data is None: data = {} return self._instantiate(schema, data) def _instantiate(self, schema, data): '''Construct an instance of *schema* using initial *data*.''' required_properties = schema.get('required', []) for key, value in schema.get('properties').items(): required = key in required_properties datatype = value.get('type') if not required: # Don't recursively process non-required non-objects. if datatype != 'object': continue # Don't recursively process objects that are not required if # the object does not already exist on the instance. if key not in data: continue if datatype == 'object': # Recursively process objects. data.setdefault(key, {}) self._instantiate(value, data[key]) else: # Set default values. default = value.get('default') if default: data.setdefault(key, default) return data def validate(self, instance, additional_schemas=None): '''Validate *instance*. If *additional_schemas* is supplied, will also validate against those. Each schema may be either a registered schema id or a schema object. Return any errors as a list of objects containing full diagnostic information. ''' # Validate against base system requirements. errors = self._validate(instance, ['harmony:/base']) if errors: return errors # Validate against specified harmony schema. errors = self._validate(instance, [instance['harmony_type']]) if errors: return errors # Validate against additional schemas if required. if additional_schemas is not None: errors = self._validate(instance, additional_schemas) return errors return [] def _validate(self, instance, schemas): '''Validate *instance* against *schemas*. Each schema may be either a registered schema id or a schema object. Return any errors as a list of objects containing full diagnostic information. ''' errors = [] for schema in schemas: if isinstance(schema, basestring): schema = self.schemas.get(schema) validator = self.validator_class(schema) validator_errors = list(validator.iter_errors(instance)) for error in validator_errors: error.schema = schema errors.extend(validator_errors) return errors
class Session(object): '''A configuration of the various components in a standard way.''' #: The default schema search path. DEFAULT_SCHEMA_PATH = os.path.join(os.path.dirname(__file__), '..', '..', 'resource', 'schema') def __init__(self, collector=None, processors=None, validator_class=None): '''Initialise session. *collector* is used to collect schemas for use in the session and should conform to the :py:class:`~harmony.schema.collector.Collector` interface. Defaults to a :py:class:`~harmony.schema.collector.FileSystemCollector` using the environment variable :envvar:`HARMONY_SCHEMA_PATH` to discover schemas. *processors* specifies a list of :py:class:`~harmony.schema.processor.Processor` instances that will post-process any discovered schemas. If not specified will default to [:py:class:`~harmony.schema.processor.ValidateProcessor`, :py:class:`~harmony.schema.processor.MixinProcessor`]. *validator_class* should be the class to use for validation of schemas and instances. Defaults to :py:class:`harmony.schema.validator.Validator`. ''' self.schemas = Collection() self.collector = collector if self.collector is None: paths = os.environ.get('HARMONY_SCHEMA_PATH', self.DEFAULT_SCHEMA_PATH).split(os.pathsep) self.collector = FilesystemCollector(paths) self.validator_class = validator_class if self.validator_class is None: self.validator_class = Validator self.processors = processors if self.processors is None: self.processors = [ ValidateProcessor(self.validator_class), MixinProcessor() ] self.refresh() def refresh(self): '''Discover schemas and add to local collection. .. note:: Collection will be processed with self.processors. ''' self.schemas.clear() for schema in self.collector.collect(): self.schemas.add(schema) for processor in self.processors: processor.process(self.schemas) def instantiate(self, schema, data=None): '''Instantiate *schema* with initial *data*. *schema* may be either a registered schema id or a schema object. Only required properties with default values will be used from the schema to construct the instance. Any values in *data* will take precedence over those in the schema. ''' if isinstance(schema, basestring): schema = self.schemas.get(schema) if data is None: data = {} return self._instantiate(schema, data) def _instantiate(self, schema, data): '''Construct an instance of *schema* using initial *data*.''' required_properties = schema.get('required', []) for key, value in schema.get('properties').items(): required = key in required_properties datatype = value.get('type') if not required: # Don't recursively process non-required non-objects. if datatype != 'object': continue # Don't recursively process objects that are not required if # the object does not already exist on the instance. if key not in data: continue if datatype == 'object': # Recursively process objects. data.setdefault(key, {}) self._instantiate(value, data[key]) else: # Set default values. default = value.get('default') if default: data.setdefault(key, default) return data def validate(self, instance, additional_schemas=None): '''Validate *instance*. If *additional_schemas* is supplied, will also validate against those. Each schema may be either a registered schema id or a schema object. Return any errors as a list of objects containing full diagnostic information. ''' # Validate against base system requirements. errors = self._validate(instance, ['harmony:/base']) if errors: return errors # Validate against specified harmony schema. errors = self._validate(instance, [instance['harmony_type']]) if errors: return errors # Validate against additional schemas if required. if additional_schemas is not None: errors = self._validate(instance, additional_schemas) return errors return [] def _validate(self, instance, schemas): '''Validate *instance* against *schemas*. Each schema may be either a registered schema id or a schema object. Return any errors as a list of objects containing full diagnostic information. ''' errors = [] for schema in schemas: if isinstance(schema, basestring): schema = self.schemas.get(schema) validator = self.validator_class(schema) validator_errors = list(validator.iter_errors(instance)) for error in validator_errors: error.schema = schema errors.extend(validator_errors) return errors