Skip to content
Merged
13 changes: 10 additions & 3 deletions src/pyhf/pdf.py
Original file line number Diff line number Diff line change
Expand Up @@ -635,14 +635,21 @@ class Model:
"""The main pyhf model class."""

def __init__(
self, spec, modifier_set=None, batch_size=None, validate=True, **config_kwargs
self,
spec,
modifier_set=None,
batch_size=None,
validate: bool = True,
**config_kwargs,
):
"""
Construct a HistFactory Model.

Args:
spec (:obj:`jsonable`): The HistFactory JSON specification
batch_size (:obj:`None` or :obj:`int`): Number of simultaneous (batched) Models to compute.
batch_size (:obj:`None` or :obj:`int`): Number of simultaneous (batched)
Models to compute.
validate (:obj:`bool`): Whether to validate against a JSON schema
config_kwargs: Possible keyword arguments for the model configuration

Returns:
Expand All @@ -657,8 +664,8 @@ def __init__(
self.schema = config_kwargs.pop('schema', 'model.json')
self.version = config_kwargs.pop('version', None)
# run jsonschema validation of input specification against the (provided) schema
log.info(f"Validating spec against schema: {self.schema:s}")
if validate:
log.info(f"Validating spec against schema: {self.schema:s}")
utils.validate(self.spec, self.schema, version=self.version)
# build up our representation of the specification
poi_name = config_kwargs.pop('poi_name', 'mu')
Expand Down
25 changes: 19 additions & 6 deletions src/pyhf/workspace.py
Original file line number Diff line number Diff line change
Expand Up @@ -286,16 +286,28 @@ class Workspace(_ChannelSummaryMixin, dict):

valid_joins = ['none', 'outer', 'left outer', 'right outer']

def __init__(self, spec, **config_kwargs):
"""Workspaces hold the model, data and measurements."""
def __init__(self, spec, validate: bool = True, **config_kwargs):
"""
Workspaces hold the model, data and measurements.

Args:
spec (:obj:`jsonable`): The HistFactory JSON specification
validate (:obj:`bool`): Whether to validate against a JSON schema
config_kwargs: Possible keyword arguments for the workspace configuration

Returns:
model (:class:`~pyhf.workspace.Workspace`): The Workspace instance

"""
spec = copy.deepcopy(spec)
super().__init__(spec, channels=spec['channels'])
self.schema = config_kwargs.pop('schema', 'workspace.json')
self.version = config_kwargs.pop('version', spec.get('version', None))

# run jsonschema validation of input specification against the (provided) schema
log.info(f"Validating spec against schema: {self.schema}")
utils.validate(self, self.schema, version=self.version)
if validate:
log.info(f"Validating spec against schema: {self.schema}")
utils.validate(self, self.schema, version=self.version)

self.measurement_names = []
for measurement in self.get('measurements', []):
Expand Down Expand Up @@ -784,14 +796,15 @@ def sorted(cls, workspace):
return cls(newspec)

@classmethod
def build(cls, model, data, name='measurement'):
def build(cls, model, data, name='measurement', validate: bool = True):
"""
Build a workspace from model and data.

Args:
model (~pyhf.pdf.Model): A model to store into a workspace
data (:obj:`tensor`): A array holding observations to store into a workspace
name (:obj:`str`): The name of the workspace measurement
validate (:obj:`bool`): Whether to validate against a JSON schema

Returns:
~pyhf.workspace.Workspace: A new workspace object
Expand Down Expand Up @@ -823,4 +836,4 @@ def build(cls, model, data, name='measurement'):
{'name': k, 'data': list(data[model.config.channel_slices[k]])}
for k in model.config.channels
]
return cls(workspace)
return cls(workspace, validate=validate)
11 changes: 11 additions & 0 deletions tests/test_workspace.py
Original file line number Diff line number Diff line change
Expand Up @@ -898,3 +898,14 @@ def test_wspace_unexpected_keyword_argument(simplemodels_model_data):

with pytest.raises(pyhf.exceptions.Unsupported):
pyhf.Workspace(spec, abc=True)


def test_workspace_without_validation(mocker, simplemodels_model_data):
model, data = simplemodels_model_data

mocker.patch('pyhf.utils.validate')
ws = pyhf.Workspace.build(model, data, validate=False)
assert pyhf.utils.validate.called is False

pyhf.Workspace(dict(ws), validate=False)
assert pyhf.utils.validate.called is False