Skip to content

Commit

Permalink
feat: Add contextlib support to pyhf.schema API (#1818)
Browse files Browse the repository at this point in the history
* Add contextlib support to the pyhf.schema API.
   - Follow up to PR #1753.
* Add tests for use of the schema contextlib to tests/test_schema.py.
* Add tests for use of the schema contextlib to the public API tests.
  • Loading branch information
kratsg authored Mar 23, 2022
1 parent 6d03b9e commit 569f512
Show file tree
Hide file tree
Showing 3 changed files with 102 additions and 12 deletions.
48 changes: 42 additions & 6 deletions src/pyhf/schema/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,17 +23,40 @@ class Schema(sys.modules[__name__].__class__):
"""
A module-level wrapper around :mod:`pyhf.schema` which will provide additional functionality for interacting with schemas.
Example:
.. rubric:: Example (callable)
.. code-block:: pycon
>>> import pyhf.schema
>>> import pathlib
>>> curr_path = pyhf.schema.path
>>> curr_path # doctest: +ELLIPSIS
>>> curr_path # doctest: +ELLIPSIS
PosixPath('.../pyhf/schemas')
>>> pyhf.schema(pathlib.Path('/home/root/my/new/path'))
>>> new_path = pathlib.Path("/home/root/my/new/path")
>>> pyhf.schema(new_path) # doctest: +ELLIPSIS
<module 'pyhf.schema' from ...>
>>> pyhf.schema.path
PosixPath('/home/root/my/new/path')
>>> pyhf.schema(curr_path)
>>> pyhf.schema.path # doctest: +ELLIPSIS
>>> pyhf.schema(curr_path) # doctest: +ELLIPSIS
<module 'pyhf.schema' from ...>
>>> pyhf.schema.path # doctest: +ELLIPSIS
PosixPath('.../pyhf/schemas')
.. rubric:: Example (context-manager)
.. code-block:: pycon
>>> import pyhf.schema
>>> import pathlib
>>> curr_path = pyhf.schema.path
>>> curr_path # doctest: +ELLIPSIS
PosixPath('.../pyhf/schemas')
>>> new_path = pathlib.Path("/home/root/my/new/path")
>>> with pyhf.schema(new_path):
... print(repr(pyhf.schema.path))
...
PosixPath('/home/root/my/new/path')
>>> pyhf.schema.path # doctest: +ELLIPSIS
PosixPath('.../pyhf/schemas')
"""
Expand All @@ -45,10 +68,23 @@ def __call__(self, new_path: pathlib.Path):
Args:
new_path (pathlib.Path): Path to folder containing the schemas
Returns:
self (pyhf.schema.Schema): Returns itself (for contextlib management)
"""
self.orig_path, variables.schemas = variables.schemas, new_path
return self

def __enter__(self):
pass

def __exit__(self, *args, **kwargs):
"""
Reset the local search path for finding schemas locally.
Returns:
None
"""
variables.schemas = new_path
variables.schemas = self.orig_path

@property
def path(self):
Expand Down
21 changes: 21 additions & 0 deletions tests/test_public_api.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import pytest
import pyhf
import numpy as np
import pathlib


@pytest.fixture(scope='function')
Expand Down Expand Up @@ -200,3 +201,23 @@ def test_pdf_batched(backend):

model.pdf(pars, data)
model.expected_data(pars)


def test_set_schema_path(monkeypatch):
monkeypatch.setattr(
pyhf.schema.variables, 'schemas', pyhf.schema.variables.schemas, raising=True
)

new_path = pathlib.Path('a/new/path')
pyhf.schema(new_path)
assert pyhf.schema.path == new_path


def test_set_schema_path_context(monkeypatch):
monkeypatch.setattr(
pyhf.schema.variables, 'schemas', pyhf.schema.variables.schemas, raising=True
)

new_path = pathlib.Path('a/new/path')
with pyhf.schema(new_path):
assert pyhf.schema.path == new_path
45 changes: 39 additions & 6 deletions tests/test_schema.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,18 +27,51 @@ def test_schema_callable():
assert callable(pyhf.schema)


def test_schema_changeable(datadir):
def test_schema_changeable(datadir, monkeypatch):
monkeypatch.setattr(
pyhf.schema.variables, 'schemas', pyhf.schema.variables.schemas, raising=True
)
old_path = pyhf.schema.path
new_path = datadir / 'customschema'

with pytest.raises(pyhf.exceptions.SchemaNotFound):
pyhf.Workspace(json.load(open(datadir / 'customschema' / 'custom.json')))

old_path = pyhf.schema.path
pyhf.schema(datadir / 'customschema')
assert pyhf.schema.path != old_path
assert pyhf.schema.path == datadir / 'customschema'
assert pyhf.Workspace(json.load(open(datadir / 'customschema' / 'custom.json')))
pyhf.schema(new_path)
assert old_path != pyhf.schema.path
assert new_path == pyhf.schema.path
assert pyhf.Workspace(json.load(open(new_path / 'custom.json')))
pyhf.schema(old_path)


def test_schema_changeable_context(datadir, monkeypatch):
monkeypatch.setattr(
pyhf.schema.variables, 'schemas', pyhf.schema.variables.schemas, raising=True
)
old_path = pyhf.schema.path
new_path = datadir / 'customschema'

assert old_path == pyhf.schema.path
with pyhf.schema(new_path):
assert old_path != pyhf.schema.path
assert new_path == pyhf.schema.path
assert pyhf.Workspace(json.load(open(new_path / 'custom.json')))
assert old_path == pyhf.schema.path


def test_schema_changeable_context_error(datadir, monkeypatch):
monkeypatch.setattr(
pyhf.schema.variables, 'schemas', pyhf.schema.variables.schemas, raising=True
)
old_path = pyhf.schema.path
new_path = datadir / 'customschema'

with pytest.raises(ZeroDivisionError):
with pyhf.schema(new_path):
raise ZeroDivisionError()
assert old_path == pyhf.schema.path


def test_no_channels():
spec = {'channels': []}
with pytest.raises(pyhf.exceptions.InvalidSpecification):
Expand Down

0 comments on commit 569f512

Please sign in to comment.