Source code for schrodinger.application.jaguar.workflow_keywords
"""
This module documents all machinery for workflow input keywords.
"""
# Contributors: Mark A. Watson
from voluptuous import Any
from voluptuous import MultipleInvalid
from voluptuous import Required
from voluptuous import Schema
from schrodinger.application.jaguar import workflow_validation as wv
#------------------------------------------------------------------------------
[docs]class Choices(object):
[docs] def __init__(self, *choices):
self.choices = choices
[docs]class WorkflowKeyword(object):
[docs] def __init__(self, name, valid_type, default, description):
"""
:type name: string
:param name: unique name for keyword
:type valid_type: python type
:param valid_type: keyword type e.g. bool, int
:type default: <valid_type>
:param default: default keyword value
:type description: string
:param description: short description of what the keyword does
"""
# Define all keywords in lower case
namel = name.lower()
self._value = None
# Define all keywords in lower case
self._name = namel
self._default = default
self._description = description
# Use Schema to establish the valid type(s) of this keyword
req = Required(namel, default=default)
if isinstance(valid_type, Choices):
sch = {req: Any(*valid_type.choices)}
self._type = valid_type.choices
else:
sch = {req: valid_type}
self._type = valid_type
self._schema = Schema(sch)
self.validate()
def __repr__(self):
return f"<{type(self).__name__} {self.name}: {repr(self.value)}>"
@property
def name(self):
return self._name
@property
def valid_type(self):
return self._type
@property
def default(self):
return self._default
@property
def description(self):
return self._description
@property
def value(self):
"""
Return user-set value.
If None, return default value.
"""
if self._value is not None:
return self._value
else:
return self._default
@value.setter
def value(self, value):
self.setValue(value)
[docs] def setValue(self, value):
"""
Set to user-defined value.
:type value: anything
:type value: user-defined value (e.g. from input file)
"""
self._value = value
self.validate()
[docs] def reset(self):
"""
Reset user-value to NoneType.
"""
self._value = None
self.validate()
[docs] def isNonDefault(self):
"""
Return True if keyword user-value differs from default value.
False otherwise.
:rtype: bool
"""
return (self.value != self._default)
[docs] def validate(self):
"""
Raise MultipleInvalid or WorkflowKeywordException if keyword
name/value don't conform to the schema. (i.e. type check)
"""
# Add an explicit check for integers since volutuous.Schema
# apparently doesn't raise an Exception when a bool is offered
# in place of an int. (JAGUAR-7460)
if isinstance(self.value, bool) and self.valid_type != bool:
raise wv.WorkflowKeywordValueTypeError(self.name, self.value,
self.valid_type)
# Check all other types using Schema
try:
self._schema({self.name: self.value})
except MultipleInvalid as e:
wv.raise_voluptuous_exception(e, self)