-
Notifications
You must be signed in to change notification settings - Fork 81
/
patchset.py
125 lines (97 loc) · 3.74 KB
/
patchset.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
"""The pyhf spec CLI subcommand."""
import logging
import click
import json
from ..patchset import PatchSet
from ..workspace import Workspace
logging.basicConfig()
log = logging.getLogger(__name__)
@click.group(name='patchset')
def cli():
"""Operations involving patchsets."""
@cli.command()
@click.argument('patchset', default='-')
@click.option('--name', help='The name of the patch to extract.', default=None)
@click.option(
'--output-file',
help='The location of the output json file. If not specified, prints to screen.',
default=None,
)
@click.option(
'--with-metadata/--without-metadata',
default=False,
help="Include patchset metadata in output.",
)
def extract(patchset, name, output_file, with_metadata):
"""
Extract a patch from a patchset.
Raises:
:class:`~pyhf.exceptions.InvalidPatchLookup`: if the provided patch name is not in the patchset
Returns:
jsonpatch (:obj:`list`): A list of jsonpatch operations to apply to a workspace.
"""
with click.open_file(patchset, 'r') as fstream:
patchset_spec = json.load(fstream)
patchset = PatchSet(patchset_spec)
patch = patchset[name]
if with_metadata:
result = {'metadata': patch.metadata, 'patch': patch.patch}
result['metadata'].update(patchset.metadata)
else:
result = patch.patch
if output_file:
with open(output_file, 'w+') as out_file:
json.dump(result, out_file, indent=4, sort_keys=True)
log.debug("Written to {0:s}".format(output_file))
else:
click.echo(json.dumps(result, indent=4, sort_keys=True))
@cli.command()
@click.argument('background-only', default='-')
@click.argument('patchset', default='-')
@click.option('--name', help='The name of the patch to extract.', default=None)
@click.option(
'--output-file',
help='The location of the output json file. If not specified, prints to screen.',
default=None,
)
def apply(background_only, patchset, name, output_file):
"""
Apply a patch from patchset to the background-only workspace specification.
Raises:
:class:`~pyhf.exceptions.InvalidPatchLookup`: if the provided patch name is not in the patchset
:class:`~pyhf.exceptions.PatchSetVerificationError`: if the patchset cannot be verified against the workspace specification
Returns:
workspace (:class:`~pyhf.workspace.Workspace`): The patched background-only workspace.
"""
with click.open_file(background_only, 'r') as specstream:
spec = json.load(specstream)
ws = Workspace(spec)
with click.open_file(patchset, 'r') as fstream:
patchset_spec = json.load(fstream)
patchset = PatchSet(patchset_spec)
patched_ws = patchset.apply(ws, name)
if output_file:
with open(output_file, 'w+') as out_file:
json.dump(patched_ws, out_file, indent=4, sort_keys=True)
log.debug("Written to {0:s}".format(output_file))
else:
click.echo(json.dumps(patched_ws, indent=4, sort_keys=True))
@cli.command()
@click.argument('background-only', default='-')
@click.argument('patchset', default='-')
def verify(background_only, patchset):
"""
Verify the patchset digests against a background-only workspace specification. Verified if no exception was raised.
Raises:
:class:`~pyhf.exceptions.PatchSetVerificationError`: if the patchset cannot be verified against the workspace specification
Returns:
None
"""
with click.open_file(background_only, 'r') as specstream:
spec = json.load(specstream)
ws = Workspace(spec)
with click.open_file(patchset, 'r') as fstream:
patchset_spec = json.load(fstream)
patchset = PatchSet(patchset_spec)
patchset.verify(ws)
click.echo("All good.")