energyplus-toolkit 0.1.0__py3-none-any.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.
@@ -0,0 +1,5 @@
1
+ """Top-level package for energyplus-toolkit."""
2
+
3
+ __author__ = """Julien Marrec"""
4
+ __email__ = 'contact@effibem.com'
5
+ __version__ = '0.1.0'
@@ -0,0 +1,150 @@
1
+ """Command-line interface: energyplus-toolkit COMMAND ...
2
+
3
+ energyplus-toolkit format idf|idd|unit-test PATH...: works like black, give it files and/or folders, they are
4
+ reformatted in place, in parallel. Use --check or --diff to only see what would change.
5
+ """
6
+
7
+ from __future__ import annotations
8
+
9
+ import argparse
10
+ import re
11
+ import sys
12
+ from pathlib import Path
13
+
14
+ from energyplus_toolkit.format import runner
15
+ from energyplus_toolkit.format.runner import Job, Kind, Mode
16
+ from energyplus_toolkit.input.idf import idf_constants
17
+
18
+ DESCRIPTIONS = {
19
+ Kind.IDF: "Reformat EnergyPlus IDF files.",
20
+ Kind.IDD: "Reformat EnergyPlus IDD files.",
21
+ Kind.UNIT_TEST: (
22
+ 'Reformat the IDF embedded in EnergyPlus C++ unit tests, in delimited_string({...}) and R"IDF(...)IDF" blocks.'
23
+ ),
24
+ }
25
+
26
+
27
+ def _add_format_subcommand(subparsers, name: str, kind: Kind) -> None:
28
+ p = subparsers.add_parser(name, help=DESCRIPTIONS[kind], description=DESCRIPTIONS[kind])
29
+ patterns = ", ".join(f"*{s}" for s in kind.suffixes)
30
+ p.add_argument(
31
+ "paths",
32
+ type=Path,
33
+ nargs="+",
34
+ metavar="PATH",
35
+ help=f"Files or folders. Folders are searched recursively for {patterns}.",
36
+ )
37
+ if kind.needs_idd:
38
+ p.add_argument(
39
+ "--idd", dest="idd_path", type=Path, required=True, metavar="IDD_PATH", help="Path to the IDD file."
40
+ )
41
+ mode = p.add_mutually_exclusive_group()
42
+ mode.add_argument(
43
+ "--check", action="store_true", help="Don't write: list the files that would change, exit 1 if any."
44
+ )
45
+ mode.add_argument("--diff", action="store_true", help="Don't write: print a unified diff of the changes.")
46
+ mode.add_argument(
47
+ "-o",
48
+ "--output",
49
+ dest="output_path",
50
+ type=Path,
51
+ metavar="OUTPUT_PATH",
52
+ help="Write to this file instead of in place ('-' for stdout). Only with a single input file.",
53
+ )
54
+ p.add_argument(
55
+ "--exclude",
56
+ type=re.compile,
57
+ metavar="REGEX",
58
+ help="Skip files found in folders whose path matches this regex. Files given explicitly are always processed.",
59
+ )
60
+ p.add_argument(
61
+ "-j",
62
+ "--workers",
63
+ type=int,
64
+ default=None,
65
+ metavar="N",
66
+ help="Number of parallel processes (default: number of CPUs).",
67
+ )
68
+ p.add_argument("-q", "--quiet", action="store_true", help="Only print errors and the summary.")
69
+ if kind is not Kind.IDD:
70
+ p.add_argument(
71
+ "--leading",
72
+ dest="idf_leading",
73
+ type=int,
74
+ default=None,
75
+ metavar="N",
76
+ help=f"Leading spaces before each object-type line (default: {idf_constants.IDF_LEADING}).",
77
+ )
78
+ p.add_argument(
79
+ "--keep-integer-reals",
80
+ action="store_true",
81
+ help='Keep a number written as an integer as is in a real field ("8" instead of "8.0").',
82
+ )
83
+ p.set_defaults(kind=kind)
84
+
85
+
86
+ def get_parser() -> argparse.ArgumentParser:
87
+ parser = argparse.ArgumentParser(prog="energyplus-toolkit", description="Tools for EnergyPlus input files.")
88
+ commands = parser.add_subparsers(dest="command", metavar="COMMAND")
89
+ commands.required = True
90
+
91
+ format_parser = commands.add_parser(
92
+ "format", help="Reformat EnergyPlus files.", description="Reformat EnergyPlus files."
93
+ )
94
+ kinds = format_parser.add_subparsers(dest="kind_name", metavar="KIND")
95
+ kinds.required = True
96
+ _add_format_subcommand(kinds, "idf", Kind.IDF)
97
+ _add_format_subcommand(kinds, "idd", Kind.IDD)
98
+ _add_format_subcommand(kinds, "unit-test", Kind.UNIT_TEST)
99
+ return parser
100
+
101
+
102
+ def _make_job(args, parser: argparse.ArgumentParser) -> Job:
103
+ kind: Kind = args.kind
104
+ idd_path = getattr(args, "idd_path", None)
105
+ if idd_path is not None and not idd_path.is_file():
106
+ parser.error(f"IDD file not found: {idd_path}")
107
+ constants: list[tuple[str, object]] = []
108
+ if getattr(args, "idf_leading", None) is not None:
109
+ if args.idf_leading < 0:
110
+ parser.error("--leading must be a non-negative integer.")
111
+ constants.append(("IDF_LEADING", args.idf_leading))
112
+ if getattr(args, "keep_integer_reals", False):
113
+ constants.append(("IDF_KEEP_INTEGER_REALS", True))
114
+ mode = Mode.CHECK if args.check else Mode.DIFF if args.diff else Mode.WRITE
115
+ return Job(kind=kind, mode=mode, idd_path=idd_path, constants=tuple(constants))
116
+
117
+
118
+ def main(args_: list[str] | None = None) -> int:
119
+ parser = get_parser()
120
+ args = parser.parse_args(args_)
121
+
122
+ for path in args.paths:
123
+ if not path.exists():
124
+ parser.error(f"path not found: {path}")
125
+ if args.workers is not None and args.workers < 1:
126
+ parser.error("--workers must be at least 1.")
127
+ job = _make_job(args, parser)
128
+
129
+ if args.output_path is not None:
130
+ # Single file, written elsewhere
131
+ if len(args.paths) != 1 or args.paths[0].is_dir():
132
+ parser.error("-o/--output needs exactly one input file.")
133
+ runner.init_worker(job)
134
+ text = runner.reformat_text(job.kind, args.paths[0].read_text(encoding="utf-8"))
135
+ if str(args.output_path) == "-":
136
+ sys.stdout.write(text)
137
+ else:
138
+ args.output_path.write_text(text, encoding="utf-8")
139
+ return 0
140
+
141
+ files = runner.collect_files(args.paths, job.kind, args.exclude)
142
+ if not files:
143
+ print("No files to reformat.", file=sys.stderr)
144
+ return 0
145
+ results = runner.run(files, job, workers=args.workers)
146
+ return runner.report(results, job, quiet=args.quiet)
147
+
148
+
149
+ if __name__ == "__main__": # pragma: no cover
150
+ sys.exit(main())
@@ -0,0 +1 @@
1
+ """Formatting EnergyPlus files: IDF, IDD, and the IDF in EnergyPlus C++ unit tests."""
File without changes