correctionlib 2.9.0__cp313-cp313-win_arm64.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- correctionlib/JSONEncoder.py +173 -0
- correctionlib/__init__.py +15 -0
- correctionlib/_core/__init__.pyi +88 -0
- correctionlib/_core.cp313-win_arm64.pyd +0 -0
- correctionlib/binding.py +20 -0
- correctionlib/cli.py +235 -0
- correctionlib/cmake/correctionlib-targets-release.cmake +19 -0
- correctionlib/cmake/correctionlib-targets.cmake +106 -0
- correctionlib/cmake/correctionlibConfig.cmake +10 -0
- correctionlib/cmake/correctionlibConfigVersion.cmake +43 -0
- correctionlib/convert.py +260 -0
- correctionlib/highlevel.py +386 -0
- correctionlib/include/correction.h +343 -0
- correctionlib/include/correctionlib_version.h +12 -0
- correctionlib/lib/correctionlib.dll +0 -0
- correctionlib/lib/correctionlib.lib +0 -0
- correctionlib/py.typed +0 -0
- correctionlib/schemav1.py +88 -0
- correctionlib/schemav2.py +692 -0
- correctionlib/util.py +32 -0
- correctionlib/version.py +24 -0
- correctionlib-2.9.0.dist-info/METADATA +167 -0
- correctionlib-2.9.0.dist-info/RECORD +26 -0
- correctionlib-2.9.0.dist-info/WHEEL +5 -0
- correctionlib-2.9.0.dist-info/entry_points.txt +3 -0
- correctionlib-2.9.0.dist-info/licenses/LICENSE +29 -0
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
"""A custom JSON encoder for corrections
|
|
2
|
+
Author: Izaak Neutelings (March 2021)
|
|
3
|
+
Description: Write JSON with indents more compactly by collapsing some lists and dictionaries
|
|
4
|
+
Instructions: Print or write JSON dictionary 'data' as
|
|
5
|
+
import JSONEncoder
|
|
6
|
+
print(JSONEncoder.write(data,sort_keys=True,indent=2,maxlistlen=25,maxdictlen=3,breakbrackets=False))
|
|
7
|
+
print(JSONEncoder.dumps(data,sort_keys=True,indent=2,maxlistlen=25,maxdictlen=3,breakbrackets=False))
|
|
8
|
+
Adapted from:
|
|
9
|
+
https://stackoverflow.com/questions/16264515/json-dumps-custom-formatting
|
|
10
|
+
"""
|
|
11
|
+
|
|
12
|
+
import gzip
|
|
13
|
+
import json
|
|
14
|
+
import math
|
|
15
|
+
from typing import Any, List, Type # noqa: F401
|
|
16
|
+
|
|
17
|
+
import pydantic
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
def write(data: Any, fname: str, **kwargs: Any) -> None:
|
|
21
|
+
"""Help function to quickly write JSON file formatted by JSONEncoder."""
|
|
22
|
+
if fname.endswith(".json.gz"):
|
|
23
|
+
with gzip.open(fname, "wt") as fout:
|
|
24
|
+
fout.write(dumps(data, **kwargs))
|
|
25
|
+
else:
|
|
26
|
+
with open(fname, "w") as fout:
|
|
27
|
+
fout.write(dumps(data, **kwargs))
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
def dumps(data: Any, sort_keys: bool = False, **kwargs: Any) -> str:
|
|
31
|
+
"""Help function to quickly dump dictionary formatted by JSONEncoder."""
|
|
32
|
+
if isinstance(data, pydantic.BaseModel): # for pydantic
|
|
33
|
+
data = data.model_dump(mode="json", exclude_unset=True)
|
|
34
|
+
return json.dumps(data, cls=JSONEncoder, sort_keys=sort_keys, **kwargs)
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
class JSONEncoder(json.JSONEncoder):
|
|
38
|
+
"""
|
|
39
|
+
Encoder to make correctionlib JSON more compact, but still readable:
|
|
40
|
+
- keep list of primitives (int, float, str) on one line,
|
|
41
|
+
or split over several if the length is longer than a given maxlen
|
|
42
|
+
- do not break line for short dictionary if all values are primitive
|
|
43
|
+
- do not break line after bracket for first key of dictionary,
|
|
44
|
+
unless itself nested in dictionary
|
|
45
|
+
"""
|
|
46
|
+
|
|
47
|
+
def __init__(self, *args: Any, **kwargs: Any):
|
|
48
|
+
if kwargs.get("indent", None) is None:
|
|
49
|
+
kwargs["indent"] = 2
|
|
50
|
+
# maximum of primitive elements per list, before breaking lines
|
|
51
|
+
self.maxlistlen = kwargs.pop("maxlistlen", 25)
|
|
52
|
+
# maximum of primitive elements per dict, before breaking lines
|
|
53
|
+
self.maxdictlen = kwargs.pop("maxdictlen", 2)
|
|
54
|
+
# maximum length of strings in short dict, before breaking lines
|
|
55
|
+
self.maxstrlen = kwargs.pop("maxstrlen", 2 * self.maxlistlen)
|
|
56
|
+
# break after opening bracket
|
|
57
|
+
self.breakbrackets = kwargs.pop("breakbrackets", False)
|
|
58
|
+
super().__init__(*args, **kwargs)
|
|
59
|
+
self._indent = 0 # current indent
|
|
60
|
+
self.parent = type(None) # type of parent for recursive use
|
|
61
|
+
|
|
62
|
+
def encode(self, obj: Any) -> str:
|
|
63
|
+
grandparent = self.parent # type: Type[Any]
|
|
64
|
+
self.parent = type(obj)
|
|
65
|
+
retval = ""
|
|
66
|
+
if isinstance(obj, (list, tuple)): # lists, tuples
|
|
67
|
+
output = []
|
|
68
|
+
if all(
|
|
69
|
+
isinstance(x, (int, float, str)) for x in obj
|
|
70
|
+
): # list of primitives only
|
|
71
|
+
strlen = sum(len(s) for s in obj if isinstance(s, str))
|
|
72
|
+
indent_str = " " * (self._indent + self.indent) # type: ignore
|
|
73
|
+
if strlen > self.maxstrlen and any(
|
|
74
|
+
len(s) > 3 for s in obj if isinstance(s, str)
|
|
75
|
+
):
|
|
76
|
+
obj = [
|
|
77
|
+
json.dumps(s) for s in obj
|
|
78
|
+
] # convert everything into a string
|
|
79
|
+
if any(
|
|
80
|
+
len(s) > self.maxstrlen / 4 for s in obj
|
|
81
|
+
): # break list of long strings into multiple lines
|
|
82
|
+
output = obj
|
|
83
|
+
else: # group strings into several lines
|
|
84
|
+
line = [] # type: List[str]
|
|
85
|
+
nchars = 0
|
|
86
|
+
for item in obj:
|
|
87
|
+
if len(line) == 0 or nchars + len(item) < self.maxstrlen:
|
|
88
|
+
line.append(item)
|
|
89
|
+
nchars += len(item)
|
|
90
|
+
else: # new line
|
|
91
|
+
output.append(", ".join(line))
|
|
92
|
+
line = [item]
|
|
93
|
+
nchars = len(item)
|
|
94
|
+
if line:
|
|
95
|
+
output.append(", ".join(line))
|
|
96
|
+
elif len(obj) <= self.maxlistlen: # write short list on one line
|
|
97
|
+
for item in obj:
|
|
98
|
+
output.append(json.dumps(item))
|
|
99
|
+
retval = "[ " + ", ".join(output) + " ]"
|
|
100
|
+
else: # break long list into multiple lines
|
|
101
|
+
nlines = math.ceil(
|
|
102
|
+
len(obj) / float(self.maxlistlen)
|
|
103
|
+
) # number of lines
|
|
104
|
+
maxlen = int(
|
|
105
|
+
math.ceil(len(obj) / nlines)
|
|
106
|
+
) # divide evenly over nlines
|
|
107
|
+
for i in range(0, nlines):
|
|
108
|
+
line = []
|
|
109
|
+
for item in obj[i * maxlen : (i + 1) * maxlen]:
|
|
110
|
+
line.append(json.dumps(item))
|
|
111
|
+
if line:
|
|
112
|
+
output.append(", ".join(line))
|
|
113
|
+
if not retval:
|
|
114
|
+
lines = (",\n" + indent_str).join(output) # lines between brackets
|
|
115
|
+
if (
|
|
116
|
+
grandparent is dict or self.breakbrackets
|
|
117
|
+
): # break first line after opening bracket
|
|
118
|
+
retval = (
|
|
119
|
+
"[\n" + indent_str + lines + "\n" + " " * self._indent + "]"
|
|
120
|
+
)
|
|
121
|
+
else: # do not break first line
|
|
122
|
+
retval = (
|
|
123
|
+
"["
|
|
124
|
+
+ " " * (self.indent - 1) # type: ignore
|
|
125
|
+
+ lines
|
|
126
|
+
+ "\n"
|
|
127
|
+
+ " " * self._indent
|
|
128
|
+
+ "]"
|
|
129
|
+
)
|
|
130
|
+
else: # list of lists, tuples, dictionaries
|
|
131
|
+
self._indent += self.indent # type: ignore
|
|
132
|
+
indent_str = " " * self._indent
|
|
133
|
+
for item in obj:
|
|
134
|
+
output.append(indent_str + self.encode(item))
|
|
135
|
+
self._indent -= self.indent # type: ignore
|
|
136
|
+
indent_str = " " * self._indent
|
|
137
|
+
retval = "[\n" + ",\n".join(output) + "\n" + indent_str + "]"
|
|
138
|
+
elif isinstance(obj, dict): # dictionaries
|
|
139
|
+
output = []
|
|
140
|
+
if (
|
|
141
|
+
len(obj) <= self.maxdictlen
|
|
142
|
+
and all(isinstance(obj[k], (int, float, str)) for k in obj)
|
|
143
|
+
and sum(len(k) + len(obj[k]) for k in obj if isinstance(obj[k], str))
|
|
144
|
+
<= self.maxstrlen
|
|
145
|
+
): # write short dict on one line
|
|
146
|
+
retval = (
|
|
147
|
+
"{ "
|
|
148
|
+
+ ", ".join(json.dumps(k) + ": " + self.encode(obj[k]) for k in obj)
|
|
149
|
+
+ " }"
|
|
150
|
+
)
|
|
151
|
+
else: # break long dict into multiple line
|
|
152
|
+
self._indent += self.indent # type: ignore
|
|
153
|
+
indent_str = " " * self._indent
|
|
154
|
+
first = (
|
|
155
|
+
grandparent not in (type(None), dict) and not self.breakbrackets
|
|
156
|
+
) # break after opening brace
|
|
157
|
+
for key, value in obj.items():
|
|
158
|
+
valstr = self.encode(value)
|
|
159
|
+
if (
|
|
160
|
+
first and "\n" not in valstr
|
|
161
|
+
): # no break between opening brace and first key
|
|
162
|
+
row = " " * (self.indent - 1) + json.dumps(key) + ": " + valstr # type: ignore
|
|
163
|
+
else: # break before key
|
|
164
|
+
row = "\n" + indent_str + json.dumps(key) + ": " + valstr
|
|
165
|
+
output.append(row)
|
|
166
|
+
first = False
|
|
167
|
+
self._indent -= self.indent # type: ignore
|
|
168
|
+
indent_str = " " * self._indent
|
|
169
|
+
retval = "{" + ",".join(output) + "\n" + indent_str + "}"
|
|
170
|
+
else: # use default formatting
|
|
171
|
+
retval = json.dumps(obj)
|
|
172
|
+
self.parent = grandparent
|
|
173
|
+
return retval
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import sys
|
|
2
|
+
|
|
3
|
+
if sys.platform.startswith("win32"):
|
|
4
|
+
import ctypes
|
|
5
|
+
|
|
6
|
+
from .util import this_module_path
|
|
7
|
+
|
|
8
|
+
ctypes.CDLL(str(this_module_path() / "lib" / "correctionlib.dll"))
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
from .binding import register_pyroot_binding
|
|
12
|
+
from .highlevel import Correction, CorrectionSet
|
|
13
|
+
from .version import version as __version__
|
|
14
|
+
|
|
15
|
+
__all__ = ("__version__", "CorrectionSet", "Correction", "register_pyroot_binding")
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
from typing import Any, Dict, Iterator, List, Type, TypeVar, Union
|
|
2
|
+
|
|
3
|
+
import numpy
|
|
4
|
+
|
|
5
|
+
class Variable:
|
|
6
|
+
@property
|
|
7
|
+
def name(self) -> str: ...
|
|
8
|
+
@property
|
|
9
|
+
def description(self) -> str: ...
|
|
10
|
+
@property
|
|
11
|
+
def type(self) -> str: ...
|
|
12
|
+
@staticmethod
|
|
13
|
+
def from_string(json: str) -> Variable: ...
|
|
14
|
+
|
|
15
|
+
class CompoundCorrection:
|
|
16
|
+
@property
|
|
17
|
+
def name(self) -> str: ...
|
|
18
|
+
@property
|
|
19
|
+
def description(self) -> str: ...
|
|
20
|
+
@property
|
|
21
|
+
def inputs(self) -> List[Variable]: ...
|
|
22
|
+
@property
|
|
23
|
+
def output(self) -> Variable: ...
|
|
24
|
+
def evaluate(self, *args: Union[str, int, float]) -> float: ...
|
|
25
|
+
def evalv(
|
|
26
|
+
self, *args: Union[numpy.ndarray[Any, Any], str, int, float]
|
|
27
|
+
) -> numpy.ndarray[Any, numpy.dtype[numpy.float64]]: ...
|
|
28
|
+
|
|
29
|
+
class Correction:
|
|
30
|
+
@property
|
|
31
|
+
def name(self) -> str: ...
|
|
32
|
+
@property
|
|
33
|
+
def description(self) -> str: ...
|
|
34
|
+
@property
|
|
35
|
+
def version(self) -> int: ...
|
|
36
|
+
@property
|
|
37
|
+
def inputs(self) -> List[Variable]: ...
|
|
38
|
+
@property
|
|
39
|
+
def output(self) -> Variable: ...
|
|
40
|
+
def evaluate(self, *args: Union[str, int, float]) -> float: ...
|
|
41
|
+
def evalv(
|
|
42
|
+
self, *args: Union[numpy.ndarray[Any, Any], str, int, float]
|
|
43
|
+
) -> numpy.ndarray[Any, numpy.dtype[numpy.float64]]: ...
|
|
44
|
+
|
|
45
|
+
T = TypeVar("T", bound="CorrectionSet")
|
|
46
|
+
|
|
47
|
+
class CorrectionSet:
|
|
48
|
+
@classmethod
|
|
49
|
+
def from_file(cls: Type[T], filename: str) -> T: ...
|
|
50
|
+
@classmethod
|
|
51
|
+
def from_string(cls: Type[T], data: str) -> T: ...
|
|
52
|
+
@property
|
|
53
|
+
def schema_version(self) -> int: ...
|
|
54
|
+
@property
|
|
55
|
+
def description(self) -> str: ...
|
|
56
|
+
def __getitem__(self, key: str) -> Correction: ...
|
|
57
|
+
def __len__(self) -> int: ...
|
|
58
|
+
def __iter__(self) -> Iterator[str]: ...
|
|
59
|
+
@property
|
|
60
|
+
def compound(self) -> Dict[str, CompoundCorrection]: ...
|
|
61
|
+
|
|
62
|
+
class FormulaAst:
|
|
63
|
+
class NodeType:
|
|
64
|
+
name: str
|
|
65
|
+
value: int
|
|
66
|
+
|
|
67
|
+
class UnaryOp:
|
|
68
|
+
name: str
|
|
69
|
+
value: int
|
|
70
|
+
|
|
71
|
+
class BinaryOp:
|
|
72
|
+
name: str
|
|
73
|
+
value: int
|
|
74
|
+
|
|
75
|
+
@property
|
|
76
|
+
def nodetype(self) -> NodeType: ...
|
|
77
|
+
@property
|
|
78
|
+
def data(self) -> Union[None, float, int, UnaryOp, BinaryOp]: ...
|
|
79
|
+
@property
|
|
80
|
+
def children(self) -> list[FormulaAst]: ...
|
|
81
|
+
|
|
82
|
+
class Formula:
|
|
83
|
+
@property
|
|
84
|
+
def expression(self) -> str: ...
|
|
85
|
+
@property
|
|
86
|
+
def ast(self) -> FormulaAst: ...
|
|
87
|
+
@classmethod
|
|
88
|
+
def from_string(cls, data: str, inputs: List[Variable]) -> Formula: ...
|
|
Binary file
|
correctionlib/binding.py
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
def register_pyroot_binding() -> None:
|
|
2
|
+
import sys
|
|
3
|
+
|
|
4
|
+
from cppyy import gbl
|
|
5
|
+
|
|
6
|
+
from .util import artifact_base_dir
|
|
7
|
+
|
|
8
|
+
base_path = artifact_base_dir()
|
|
9
|
+
lib = base_path / "lib"
|
|
10
|
+
|
|
11
|
+
# maybe not the most robust solution?
|
|
12
|
+
if sys.platform.startswith("win32"):
|
|
13
|
+
lib = lib / "correctionlib.dll"
|
|
14
|
+
elif sys.platform.startswith("darwin"):
|
|
15
|
+
lib = lib / "libcorrectionlib.dylib"
|
|
16
|
+
else:
|
|
17
|
+
lib = lib / "libcorrectionlib.so"
|
|
18
|
+
gbl.gSystem.Load(str(lib))
|
|
19
|
+
gbl.gInterpreter.AddIncludePath(str(base_path / "include"))
|
|
20
|
+
gbl.gROOT.ProcessLine('#include "correction.h"')
|
correctionlib/cli.py
ADDED
|
@@ -0,0 +1,235 @@
|
|
|
1
|
+
"""Command-line interface to correctionlib."""
|
|
2
|
+
|
|
3
|
+
import argparse
|
|
4
|
+
import sys
|
|
5
|
+
|
|
6
|
+
import pydantic
|
|
7
|
+
from rich.console import Console
|
|
8
|
+
|
|
9
|
+
import correctionlib.version
|
|
10
|
+
from correctionlib import schemav2
|
|
11
|
+
from correctionlib.highlevel import model_auto, open_auto
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
def validate(console: Console, args: argparse.Namespace) -> int:
|
|
15
|
+
"""Check if all files are valid"""
|
|
16
|
+
if args.ignore_float_inf:
|
|
17
|
+
schemav2.IGNORE_FLOAT_INF = True
|
|
18
|
+
retcode = 0
|
|
19
|
+
for file in args.files:
|
|
20
|
+
try:
|
|
21
|
+
if not args.quiet:
|
|
22
|
+
console.rule(f"[blue]Validating file {file}")
|
|
23
|
+
cset = model_auto(open_auto(file))
|
|
24
|
+
if args.version and cset.schema_version != args.version:
|
|
25
|
+
raise ValueError(
|
|
26
|
+
f"Schema version {cset.schema_version} does not match the required version {args.version}"
|
|
27
|
+
)
|
|
28
|
+
except pydantic.ValidationError as ex:
|
|
29
|
+
if not args.quiet:
|
|
30
|
+
console.print("[red]Validation error, full information below")
|
|
31
|
+
print(str(ex)) # noqa: T201
|
|
32
|
+
retcode = 1
|
|
33
|
+
if args.failfast:
|
|
34
|
+
break
|
|
35
|
+
except BaseException:
|
|
36
|
+
if not args.quiet:
|
|
37
|
+
raise
|
|
38
|
+
retcode = 2
|
|
39
|
+
if args.failfast:
|
|
40
|
+
break
|
|
41
|
+
else:
|
|
42
|
+
if not args.quiet:
|
|
43
|
+
console.print("[green]All OK :heavy_check_mark:")
|
|
44
|
+
return retcode
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
def setup_validate(subparsers):
|
|
48
|
+
parser = subparsers.add_parser("validate", help=validate.__doc__)
|
|
49
|
+
parser.set_defaults(command=validate)
|
|
50
|
+
parser.add_argument(
|
|
51
|
+
"--quiet",
|
|
52
|
+
"-q",
|
|
53
|
+
action="store_true",
|
|
54
|
+
help="Suppress error printout, only produce a returncode",
|
|
55
|
+
)
|
|
56
|
+
parser.add_argument(
|
|
57
|
+
"--failfast",
|
|
58
|
+
"-f",
|
|
59
|
+
action="store_true",
|
|
60
|
+
help="Fail on first invalid file",
|
|
61
|
+
)
|
|
62
|
+
parser.add_argument(
|
|
63
|
+
"--version",
|
|
64
|
+
"-v",
|
|
65
|
+
type=int,
|
|
66
|
+
default=None,
|
|
67
|
+
help="Validate against specific schema version",
|
|
68
|
+
)
|
|
69
|
+
parser.add_argument(
|
|
70
|
+
"--ignore-float-inf",
|
|
71
|
+
action="store_true",
|
|
72
|
+
help="Disable errors for use of float infinities in bin edges (as required in v2.6 and later)",
|
|
73
|
+
)
|
|
74
|
+
parser.add_argument("files", nargs="+", metavar="FILE")
|
|
75
|
+
return parser
|
|
76
|
+
|
|
77
|
+
|
|
78
|
+
def summary(console: Console, args: argparse.Namespace) -> int:
|
|
79
|
+
if args.ignore_float_inf:
|
|
80
|
+
schemav2.IGNORE_FLOAT_INF = True
|
|
81
|
+
|
|
82
|
+
for file in args.files:
|
|
83
|
+
console.rule(f"[blue]Corrections in file {file}")
|
|
84
|
+
cset = model_auto(open_auto(file))
|
|
85
|
+
console.print(cset)
|
|
86
|
+
return 0
|
|
87
|
+
|
|
88
|
+
|
|
89
|
+
def setup_summary(subparsers):
|
|
90
|
+
parser = subparsers.add_parser("summary", help="Print a summary of the corrections")
|
|
91
|
+
parser.set_defaults(command=summary)
|
|
92
|
+
parser.add_argument(
|
|
93
|
+
"--ignore-float-inf",
|
|
94
|
+
action="store_true",
|
|
95
|
+
help="Disable errors for use of float infinities in bin edges (as required in v2.6 and later)",
|
|
96
|
+
)
|
|
97
|
+
parser.add_argument("files", nargs="+", metavar="FILE")
|
|
98
|
+
return parser
|
|
99
|
+
|
|
100
|
+
|
|
101
|
+
def merge(console: Console, args: argparse.Namespace) -> int:
|
|
102
|
+
cset = model_auto(open_auto(args.files[0]))
|
|
103
|
+
for file in args.files[1:]:
|
|
104
|
+
cset2 = model_auto(open_auto(file))
|
|
105
|
+
if cset2.schema_version != cset.schema_version:
|
|
106
|
+
console.print("[red]Mixed schema versions detected")
|
|
107
|
+
return 1
|
|
108
|
+
for corr2 in cset2.corrections:
|
|
109
|
+
if any(corr.name == corr2.name for corr in cset.corrections):
|
|
110
|
+
console.print(
|
|
111
|
+
f"[red]Correction {corr2.name!r} from {file} is a duplicate"
|
|
112
|
+
)
|
|
113
|
+
return 1
|
|
114
|
+
cset.corrections.append(corr2)
|
|
115
|
+
for corr2 in cset2.compound_corrections if cset2.compound_corrections else []:
|
|
116
|
+
if cset.compound_corrections is None:
|
|
117
|
+
cset.compound_corrections = []
|
|
118
|
+
if any(corr.name == corr2.name for corr in cset.compound_corrections):
|
|
119
|
+
console.print(
|
|
120
|
+
f"[red]Compound correction {corr2.name!r} from {file} is a duplicate"
|
|
121
|
+
)
|
|
122
|
+
return 1
|
|
123
|
+
cset.compound_corrections.append(corr2)
|
|
124
|
+
cset.description = "Merged from " + " ".join(args.files)
|
|
125
|
+
if args.format == "compact":
|
|
126
|
+
sys.stdout.write(cset.model_dump_json())
|
|
127
|
+
elif args.format == "indented":
|
|
128
|
+
sys.stdout.write(cset.model_dump_json(indent=4) + "\n")
|
|
129
|
+
elif args.format == "pretty":
|
|
130
|
+
from correctionlib.JSONEncoder import dumps
|
|
131
|
+
|
|
132
|
+
sys.stdout.write(dumps(cset) + "\n")
|
|
133
|
+
else:
|
|
134
|
+
return 1
|
|
135
|
+
return 0
|
|
136
|
+
|
|
137
|
+
|
|
138
|
+
def setup_merge(subparsers):
|
|
139
|
+
parser = subparsers.add_parser(
|
|
140
|
+
"merge", help="Merge one or more correction files and print to stdout"
|
|
141
|
+
)
|
|
142
|
+
parser.set_defaults(command=merge)
|
|
143
|
+
parser.add_argument(
|
|
144
|
+
"-f",
|
|
145
|
+
"--format",
|
|
146
|
+
type=str,
|
|
147
|
+
help="JSON output formatting (default: %(default)s)",
|
|
148
|
+
choices=("compact", "indented", "pretty"),
|
|
149
|
+
default="compact",
|
|
150
|
+
)
|
|
151
|
+
parser.add_argument("files", nargs="+", metavar="FILE")
|
|
152
|
+
return parser
|
|
153
|
+
|
|
154
|
+
|
|
155
|
+
def config(console: Console, args: argparse.Namespace) -> int:
|
|
156
|
+
from .util import artifact_base_dir
|
|
157
|
+
|
|
158
|
+
base_dir = artifact_base_dir()
|
|
159
|
+
incdir = base_dir / "include"
|
|
160
|
+
libdir = base_dir / "lib"
|
|
161
|
+
out = []
|
|
162
|
+
if args.version:
|
|
163
|
+
out.append(correctionlib.version.version)
|
|
164
|
+
if args.incdir:
|
|
165
|
+
out.append(str(incdir))
|
|
166
|
+
if args.cflags:
|
|
167
|
+
out.append(f"-std=c++17 -I{incdir}")
|
|
168
|
+
if args.libdir:
|
|
169
|
+
out.append(str(libdir))
|
|
170
|
+
if args.ldflags:
|
|
171
|
+
out.append(f"-L{libdir} -lcorrectionlib")
|
|
172
|
+
if args.rpath:
|
|
173
|
+
out.append(f"-Wl,-rpath,{libdir}")
|
|
174
|
+
if args.cmake:
|
|
175
|
+
out.append(f"-Dcorrectionlib_DIR={base_dir / 'cmake'}")
|
|
176
|
+
console.out(" ".join(out), highlight=False)
|
|
177
|
+
return 0
|
|
178
|
+
|
|
179
|
+
|
|
180
|
+
def setup_config(subparsers):
|
|
181
|
+
parser = subparsers.add_parser(
|
|
182
|
+
"config", help="Configuration and linking information"
|
|
183
|
+
)
|
|
184
|
+
parser.set_defaults(command=config)
|
|
185
|
+
parser.add_argument(
|
|
186
|
+
"-v",
|
|
187
|
+
"--version",
|
|
188
|
+
action="store_true",
|
|
189
|
+
help="Return correctionlib current version",
|
|
190
|
+
)
|
|
191
|
+
parser.add_argument("--incdir", action="store_true")
|
|
192
|
+
parser.add_argument("--cflags", action="store_true")
|
|
193
|
+
parser.add_argument("--libdir", action="store_true")
|
|
194
|
+
parser.add_argument("--ldflags", action="store_true")
|
|
195
|
+
parser.add_argument(
|
|
196
|
+
"--rpath", action="store_true", help="Include library path hint in linker"
|
|
197
|
+
)
|
|
198
|
+
parser.add_argument("--cmake", action="store_true", help="CMake dependency flags")
|
|
199
|
+
return parser
|
|
200
|
+
|
|
201
|
+
|
|
202
|
+
def main() -> int:
|
|
203
|
+
parser = argparse.ArgumentParser(prog="correction", description=__doc__)
|
|
204
|
+
parser.add_argument(
|
|
205
|
+
"--width",
|
|
206
|
+
type=int,
|
|
207
|
+
default=100,
|
|
208
|
+
help="Rich output width",
|
|
209
|
+
)
|
|
210
|
+
parser.add_argument("--html", type=str, help="Save terminal output to an HTML file")
|
|
211
|
+
subparsers = parser.add_subparsers()
|
|
212
|
+
all_commands = []
|
|
213
|
+
all_commands.append(setup_validate(subparsers))
|
|
214
|
+
all_commands.append(setup_summary(subparsers))
|
|
215
|
+
all_commands.append(setup_merge(subparsers))
|
|
216
|
+
all_commands.append(setup_config(subparsers))
|
|
217
|
+
args = parser.parse_args()
|
|
218
|
+
|
|
219
|
+
console = Console(width=args.width, record=bool(args.html))
|
|
220
|
+
if hasattr(args, "command"):
|
|
221
|
+
retcode: int = args.command(console, args)
|
|
222
|
+
if args.html:
|
|
223
|
+
console.save_html(args.html)
|
|
224
|
+
return retcode
|
|
225
|
+
|
|
226
|
+
help = parser.format_help() + "\n"
|
|
227
|
+
help += "Subcommand usage (specify -h for more detail):\n"
|
|
228
|
+
for command in all_commands:
|
|
229
|
+
help += command.format_usage()
|
|
230
|
+
console.out(help, highlight=False)
|
|
231
|
+
return 0
|
|
232
|
+
|
|
233
|
+
|
|
234
|
+
if __name__ == "__main__":
|
|
235
|
+
exit(main())
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
#----------------------------------------------------------------
|
|
2
|
+
# Generated CMake target import file for configuration "Release".
|
|
3
|
+
#----------------------------------------------------------------
|
|
4
|
+
|
|
5
|
+
# Commands may need to know the format version.
|
|
6
|
+
set(CMAKE_IMPORT_FILE_VERSION 1)
|
|
7
|
+
|
|
8
|
+
# Import target "correctionlib" for configuration "Release"
|
|
9
|
+
set_property(TARGET correctionlib APPEND PROPERTY IMPORTED_CONFIGURATIONS RELEASE)
|
|
10
|
+
set_target_properties(correctionlib PROPERTIES
|
|
11
|
+
IMPORTED_IMPLIB_RELEASE "${_IMPORT_PREFIX}/correctionlib/lib/correctionlib.lib"
|
|
12
|
+
IMPORTED_LOCATION_RELEASE "${_IMPORT_PREFIX}/correctionlib/lib/correctionlib.dll"
|
|
13
|
+
)
|
|
14
|
+
|
|
15
|
+
list(APPEND _cmake_import_check_targets correctionlib )
|
|
16
|
+
list(APPEND _cmake_import_check_files_for_correctionlib "${_IMPORT_PREFIX}/correctionlib/lib/correctionlib.lib" "${_IMPORT_PREFIX}/correctionlib/lib/correctionlib.dll" )
|
|
17
|
+
|
|
18
|
+
# Commands beyond this point should not need to know the version.
|
|
19
|
+
set(CMAKE_IMPORT_FILE_VERSION)
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
# Generated by CMake
|
|
2
|
+
|
|
3
|
+
if("${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION}" LESS 2.8)
|
|
4
|
+
message(FATAL_ERROR "CMake >= 2.8.3 required")
|
|
5
|
+
endif()
|
|
6
|
+
if(CMAKE_VERSION VERSION_LESS "2.8.3")
|
|
7
|
+
message(FATAL_ERROR "CMake >= 2.8.3 required")
|
|
8
|
+
endif()
|
|
9
|
+
cmake_policy(PUSH)
|
|
10
|
+
cmake_policy(VERSION 2.8.3...4.1)
|
|
11
|
+
#----------------------------------------------------------------
|
|
12
|
+
# Generated CMake target import file.
|
|
13
|
+
#----------------------------------------------------------------
|
|
14
|
+
|
|
15
|
+
# Commands may need to know the format version.
|
|
16
|
+
set(CMAKE_IMPORT_FILE_VERSION 1)
|
|
17
|
+
|
|
18
|
+
# Protect against multiple inclusion, which would fail when already imported targets are added once more.
|
|
19
|
+
set(_cmake_targets_defined "")
|
|
20
|
+
set(_cmake_targets_not_defined "")
|
|
21
|
+
set(_cmake_expected_targets "")
|
|
22
|
+
foreach(_cmake_expected_target IN ITEMS correctionlib)
|
|
23
|
+
list(APPEND _cmake_expected_targets "${_cmake_expected_target}")
|
|
24
|
+
if(TARGET "${_cmake_expected_target}")
|
|
25
|
+
list(APPEND _cmake_targets_defined "${_cmake_expected_target}")
|
|
26
|
+
else()
|
|
27
|
+
list(APPEND _cmake_targets_not_defined "${_cmake_expected_target}")
|
|
28
|
+
endif()
|
|
29
|
+
endforeach()
|
|
30
|
+
unset(_cmake_expected_target)
|
|
31
|
+
if(_cmake_targets_defined STREQUAL _cmake_expected_targets)
|
|
32
|
+
unset(_cmake_targets_defined)
|
|
33
|
+
unset(_cmake_targets_not_defined)
|
|
34
|
+
unset(_cmake_expected_targets)
|
|
35
|
+
unset(CMAKE_IMPORT_FILE_VERSION)
|
|
36
|
+
cmake_policy(POP)
|
|
37
|
+
return()
|
|
38
|
+
endif()
|
|
39
|
+
if(NOT _cmake_targets_defined STREQUAL "")
|
|
40
|
+
string(REPLACE ";" ", " _cmake_targets_defined_text "${_cmake_targets_defined}")
|
|
41
|
+
string(REPLACE ";" ", " _cmake_targets_not_defined_text "${_cmake_targets_not_defined}")
|
|
42
|
+
message(FATAL_ERROR "Some (but not all) targets in this export set were already defined.\nTargets Defined: ${_cmake_targets_defined_text}\nTargets not yet defined: ${_cmake_targets_not_defined_text}\n")
|
|
43
|
+
endif()
|
|
44
|
+
unset(_cmake_targets_defined)
|
|
45
|
+
unset(_cmake_targets_not_defined)
|
|
46
|
+
unset(_cmake_expected_targets)
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
# Compute the installation prefix relative to this file.
|
|
50
|
+
get_filename_component(_IMPORT_PREFIX "${CMAKE_CURRENT_LIST_FILE}" PATH)
|
|
51
|
+
get_filename_component(_IMPORT_PREFIX "${_IMPORT_PREFIX}" PATH)
|
|
52
|
+
get_filename_component(_IMPORT_PREFIX "${_IMPORT_PREFIX}" PATH)
|
|
53
|
+
if(_IMPORT_PREFIX STREQUAL "/")
|
|
54
|
+
set(_IMPORT_PREFIX "")
|
|
55
|
+
endif()
|
|
56
|
+
|
|
57
|
+
# Create imported target correctionlib
|
|
58
|
+
add_library(correctionlib SHARED IMPORTED)
|
|
59
|
+
|
|
60
|
+
set_target_properties(correctionlib PROPERTIES
|
|
61
|
+
INTERFACE_COMPILE_FEATURES "cxx_std_17"
|
|
62
|
+
INTERFACE_INCLUDE_DIRECTORIES "${_IMPORT_PREFIX}/correctionlib/include"
|
|
63
|
+
)
|
|
64
|
+
|
|
65
|
+
# Load information for each installed configuration.
|
|
66
|
+
file(GLOB _cmake_config_files "${CMAKE_CURRENT_LIST_DIR}/correctionlib-targets-*.cmake")
|
|
67
|
+
foreach(_cmake_config_file IN LISTS _cmake_config_files)
|
|
68
|
+
include("${_cmake_config_file}")
|
|
69
|
+
endforeach()
|
|
70
|
+
unset(_cmake_config_file)
|
|
71
|
+
unset(_cmake_config_files)
|
|
72
|
+
|
|
73
|
+
# Cleanup temporary variables.
|
|
74
|
+
set(_IMPORT_PREFIX)
|
|
75
|
+
|
|
76
|
+
# Loop over all imported files and verify that they actually exist
|
|
77
|
+
foreach(_cmake_target IN LISTS _cmake_import_check_targets)
|
|
78
|
+
if(CMAKE_VERSION VERSION_LESS "3.28"
|
|
79
|
+
OR NOT DEFINED _cmake_import_check_xcframework_for_${_cmake_target}
|
|
80
|
+
OR NOT IS_DIRECTORY "${_cmake_import_check_xcframework_for_${_cmake_target}}")
|
|
81
|
+
foreach(_cmake_file IN LISTS "_cmake_import_check_files_for_${_cmake_target}")
|
|
82
|
+
if(NOT EXISTS "${_cmake_file}")
|
|
83
|
+
message(FATAL_ERROR "The imported target \"${_cmake_target}\" references the file
|
|
84
|
+
\"${_cmake_file}\"
|
|
85
|
+
but this file does not exist. Possible reasons include:
|
|
86
|
+
* The file was deleted, renamed, or moved to another location.
|
|
87
|
+
* An install or uninstall procedure did not complete successfully.
|
|
88
|
+
* The installation package was faulty and contained
|
|
89
|
+
\"${CMAKE_CURRENT_LIST_FILE}\"
|
|
90
|
+
but not all the files it references.
|
|
91
|
+
")
|
|
92
|
+
endif()
|
|
93
|
+
endforeach()
|
|
94
|
+
endif()
|
|
95
|
+
unset(_cmake_file)
|
|
96
|
+
unset("_cmake_import_check_files_for_${_cmake_target}")
|
|
97
|
+
endforeach()
|
|
98
|
+
unset(_cmake_target)
|
|
99
|
+
unset(_cmake_import_check_targets)
|
|
100
|
+
|
|
101
|
+
# This file does not depend on other imported targets which have
|
|
102
|
+
# been exported from the same project but in a separate export set.
|
|
103
|
+
|
|
104
|
+
# Commands beyond this point should not need to know the version.
|
|
105
|
+
set(CMAKE_IMPORT_FILE_VERSION)
|
|
106
|
+
cmake_policy(POP)
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
|
|
2
|
+
####### Expanded from @PACKAGE_INIT@ by configure_package_config_file() #######
|
|
3
|
+
####### Any changes to this file will be overwritten by the next CMake run ####
|
|
4
|
+
####### The input file was Config.cmake.in ########
|
|
5
|
+
|
|
6
|
+
get_filename_component(PACKAGE_PREFIX_DIR "${CMAKE_CURRENT_LIST_DIR}/../../" ABSOLUTE)
|
|
7
|
+
|
|
8
|
+
####################################################################################
|
|
9
|
+
|
|
10
|
+
include("${CMAKE_CURRENT_LIST_DIR}/correctionlib-targets.cmake")
|