energyplus-toolkit 0.1.0__tar.gz
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.
- energyplus_toolkit-0.1.0/PKG-INFO +148 -0
- energyplus_toolkit-0.1.0/README.md +116 -0
- energyplus_toolkit-0.1.0/energyplus_toolkit/__init__.py +5 -0
- energyplus_toolkit-0.1.0/energyplus_toolkit/cli.py +150 -0
- energyplus_toolkit-0.1.0/energyplus_toolkit/format/__init__.py +1 -0
- energyplus_toolkit-0.1.0/energyplus_toolkit/format/cpp/__init__.py +0 -0
- energyplus_toolkit-0.1.0/energyplus_toolkit/format/cpp/unit_test_file.py +666 -0
- energyplus_toolkit-0.1.0/energyplus_toolkit/format/runner.py +257 -0
- energyplus_toolkit-0.1.0/energyplus_toolkit/input/__init__.py +4 -0
- energyplus_toolkit-0.1.0/energyplus_toolkit/input/idd/__init__.py +0 -0
- energyplus_toolkit-0.1.0/energyplus_toolkit/input/idd/idd_constants.py +25 -0
- energyplus_toolkit-0.1.0/energyplus_toolkit/input/idd/idd_field.py +549 -0
- energyplus_toolkit-0.1.0/energyplus_toolkit/input/idd/idd_file.py +182 -0
- energyplus_toolkit-0.1.0/energyplus_toolkit/input/idd/idd_object.py +376 -0
- energyplus_toolkit-0.1.0/energyplus_toolkit/input/idd/idd_regex.py +80 -0
- energyplus_toolkit-0.1.0/energyplus_toolkit/input/idf/__init__.py +0 -0
- energyplus_toolkit-0.1.0/energyplus_toolkit/input/idf/idf_constants.py +48 -0
- energyplus_toolkit-0.1.0/energyplus_toolkit/input/idf/idf_field.py +435 -0
- energyplus_toolkit-0.1.0/energyplus_toolkit/input/idf/idf_file.py +278 -0
- energyplus_toolkit-0.1.0/energyplus_toolkit/input/idf/idf_object.py +507 -0
- energyplus_toolkit-0.1.0/energyplus_toolkit/input/idf/idf_regex.py +48 -0
- energyplus_toolkit-0.1.0/energyplus_toolkit.egg-info/PKG-INFO +148 -0
- energyplus_toolkit-0.1.0/energyplus_toolkit.egg-info/SOURCES.txt +29 -0
- energyplus_toolkit-0.1.0/energyplus_toolkit.egg-info/dependency_links.txt +1 -0
- energyplus_toolkit-0.1.0/energyplus_toolkit.egg-info/entry_points.txt +2 -0
- energyplus_toolkit-0.1.0/energyplus_toolkit.egg-info/requires.txt +14 -0
- energyplus_toolkit-0.1.0/energyplus_toolkit.egg-info/top_level.txt +1 -0
- energyplus_toolkit-0.1.0/pyproject.toml +89 -0
- energyplus_toolkit-0.1.0/setup.cfg +4 -0
- energyplus_toolkit-0.1.0/tests/test_cli.py +193 -0
- energyplus_toolkit-0.1.0/tests/test_layering.py +30 -0
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: energyplus-toolkit
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Tools for EnergyPlus input files: parse, write back and reformat IDD and IDF files, and the IDF in EnergyPlus C++ unit tests.
|
|
5
|
+
Author-email: Julien Marrec <contact@effibem.com>
|
|
6
|
+
License: MIT
|
|
7
|
+
Project-URL: Homepage, https://effibem.com
|
|
8
|
+
Project-URL: Repository, https://github.com/jmarrec/energyplus-toolkit
|
|
9
|
+
Project-URL: Issues, https://github.com/jmarrec/energyplus-toolkit/issues
|
|
10
|
+
Classifier: Development Status :: 2 - Pre-Alpha
|
|
11
|
+
Classifier: Intended Audience :: Developers
|
|
12
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
13
|
+
Classifier: Natural Language :: English
|
|
14
|
+
Classifier: Programming Language :: Python :: 3
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
18
|
+
Requires-Python: >=3.11
|
|
19
|
+
Description-Content-Type: text/markdown
|
|
20
|
+
Provides-Extra: test
|
|
21
|
+
Requires-Dist: pytest>=9.0.2; extra == "test"
|
|
22
|
+
Requires-Dist: pytest-cov>=7.0.0; extra == "test"
|
|
23
|
+
Provides-Extra: dev
|
|
24
|
+
Requires-Dist: pre-commit>=4.5.0; extra == "dev"
|
|
25
|
+
Requires-Dist: twine>=6.2.0; extra == "dev"
|
|
26
|
+
Requires-Dist: bump2version>=1.0.1; extra == "dev"
|
|
27
|
+
Requires-Dist: mypy>=1.19.0; extra == "dev"
|
|
28
|
+
Requires-Dist: flake8>=7.3.0; extra == "dev"
|
|
29
|
+
Requires-Dist: flake8-docstrings>=1.7.0; extra == "dev"
|
|
30
|
+
Requires-Dist: black>=25.12.0; extra == "dev"
|
|
31
|
+
Requires-Dist: isort>=7.0.0; extra == "dev"
|
|
32
|
+
|
|
33
|
+
# energyplus-toolkit
|
|
34
|
+
|
|
35
|
+
[](https://pypi.org/project/energyplus-toolkit/)
|
|
36
|
+
[](https://pypi.org/project/energyplus-toolkit/)
|
|
37
|
+
[](https://github.com/jmarrec/energyplus-toolkit/actions/workflows/dev.yml)
|
|
38
|
+
|
|
39
|
+
Tools for [EnergyPlus](https://energyplus.net) input files:
|
|
40
|
+
|
|
41
|
+
- parse IDD and IDF files, link each IDF object and field to its IDD definition, and write them back faithfully;
|
|
42
|
+
- reformat IDF and IDD files, and the IDF embedded in EnergyPlus C++ unit tests, from the command line or as
|
|
43
|
+
pre-commit hooks.
|
|
44
|
+
|
|
45
|
+
* GitHub: <https://github.com/jmarrec/energyplus-toolkit>
|
|
46
|
+
* PyPI: <https://pypi.org/project/energyplus-toolkit/>
|
|
47
|
+
|
|
48
|
+
## Installation
|
|
49
|
+
|
|
50
|
+
```bash
|
|
51
|
+
pip install energyplus-toolkit
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
Requires Python 3.11+.
|
|
55
|
+
|
|
56
|
+
For development:
|
|
57
|
+
|
|
58
|
+
```bash
|
|
59
|
+
pip install -e ".[dev,test]" # With the dev tools (pre-commit, black, isort, flake8, mypy) and the tests (pytest)
|
|
60
|
+
pre-commit install
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
## Command line
|
|
64
|
+
|
|
65
|
+
```shell
|
|
66
|
+
# Reformat in place, like black: files and/or folders (searched recursively), in parallel
|
|
67
|
+
energyplus-toolkit format idf --idd Energy+.idd testfiles/
|
|
68
|
+
energyplus-toolkit format idd Energy+.idd
|
|
69
|
+
energyplus-toolkit format unit-test --idd Energy+.idd tst/EnergyPlus/unit
|
|
70
|
+
|
|
71
|
+
# Only look: list the files that would change (exit 1 if any), or print a diff
|
|
72
|
+
energyplus-toolkit format idf --idd Energy+.idd --check testfiles/
|
|
73
|
+
energyplus-toolkit format idf --idd Energy+.idd --diff testfiles/1ZoneUncontrolled.idf
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
Options (see `--help`): `--exclude REGEX`, `-j N` workers, `-q` quiet, `-o OUTPUT` (single file, `-` for stdout),
|
|
77
|
+
and for IDF / unit tests `--leading N` (spaces before object names) and `--keep-integer-reals` (keep `8` instead of
|
|
78
|
+
writing `8.0` in a real field).
|
|
79
|
+
|
|
80
|
+
Exit codes: 0 when done, 1 if `--check` found files to reformat, 123 on error.
|
|
81
|
+
|
|
82
|
+
Content is never lost: a file or block that can't be reformatted safely (unknown object, text outside a field, IMF or
|
|
83
|
+
parametric file, C++ code building the IDF...) is left unchanged, with a warning.
|
|
84
|
+
|
|
85
|
+
## pre-commit hooks
|
|
86
|
+
|
|
87
|
+
```yaml
|
|
88
|
+
- repo: https://github.com/jmarrec/energyplus-toolkit
|
|
89
|
+
rev: v0.1.0
|
|
90
|
+
hooks:
|
|
91
|
+
- id: energyplus-format-idd
|
|
92
|
+
args: [--idd, idd/Energy+.idd.in]
|
|
93
|
+
- id: energyplus-format-idf
|
|
94
|
+
args: [--idd, idd/Energy+.idd.in, -q]
|
|
95
|
+
- id: energyplus-format-unit-test
|
|
96
|
+
args: [--idd, idd/Energy+.idd.in, -q]
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
Each hook needs the IDD to use (`--idd`). For unit tests, put the hook before clang-format: reformatting then
|
|
100
|
+
clang-format is stable.
|
|
101
|
+
|
|
102
|
+
## Library
|
|
103
|
+
|
|
104
|
+
The IDD gives each IDF object and field its definition: type, units, default, choices, extensible groups...
|
|
105
|
+
|
|
106
|
+
```python
|
|
107
|
+
from pathlib import Path
|
|
108
|
+
|
|
109
|
+
from energyplus_toolkit.input.idd.idd_file import IddFile
|
|
110
|
+
from energyplus_toolkit.input.idf.idf_file import IdfFile
|
|
111
|
+
from energyplus_toolkit.input.idf.idf_object import IdfObject
|
|
112
|
+
|
|
113
|
+
idd = IddFile.load(Path("Energy+.idd"))
|
|
114
|
+
|
|
115
|
+
# A whole IDF file: each object is linked to its IDD object
|
|
116
|
+
idf = IdfFile.load("in.idf", idd) # or IdfFile.loads(text, idd)
|
|
117
|
+
for zone in idf.get_objects_by_type("Zone"):
|
|
118
|
+
print(zone.name, zone.getDouble(1), zone.getDouble(1, return_default=True)) # "Z2 None 0.0" if left blank
|
|
119
|
+
idf.save("out.idf", overwrite=True) # or str(idf)
|
|
120
|
+
|
|
121
|
+
# A single object, from its text and its IDD object
|
|
122
|
+
zone = IdfObject.load(idd_object=idd.getObject("Zone"), text="Zone,Z3,90;")
|
|
123
|
+
zone.setDouble(1, 45.0)
|
|
124
|
+
print(zone)
|
|
125
|
+
# Zone,
|
|
126
|
+
# Z3, !- Name
|
|
127
|
+
# 45.0; !- Direction of Relative North {deg}
|
|
128
|
+
|
|
129
|
+
# Or built from scratch, with extensible groups
|
|
130
|
+
branch = IdfObject(idd_object=idd.getObject("Branch"))
|
|
131
|
+
branch.setString(0, "Supply Branch")
|
|
132
|
+
branch.push_extensible_group(["Pump:VariableSpeed", "Pump", "Pump-Inlet", "Pump-Outlet"])
|
|
133
|
+
|
|
134
|
+
# The IDD side
|
|
135
|
+
field = idd.getObject("Zone").fields[1]
|
|
136
|
+
print(field.name, field.properties.type, field.properties.units, field.properties.stringDefault)
|
|
137
|
+
# Direction of Relative North real deg 0
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
Values are validated against the IDD when set (types, choices, bounds), and the IDF is written with its comments
|
|
141
|
+
(`!- Field Name {units}`) and the layout the IDD asks for (`\format`: vertices, compact schedules...).
|
|
142
|
+
|
|
143
|
+
## Layout
|
|
144
|
+
|
|
145
|
+
- `energyplus_toolkit/input`: the EnergyPlus input data model (IDD and IDF objects, fields, their types), read from and
|
|
146
|
+
written to files. It doesn't depend on the tools, so it can become its own package.
|
|
147
|
+
- `energyplus_toolkit/format`: the formatter (parallel runner, C++ unit tests: see `format/cpp/README.md`).
|
|
148
|
+
- `energyplus_toolkit/cli.py`: the `energyplus-toolkit` command.
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
# energyplus-toolkit
|
|
2
|
+
|
|
3
|
+
[](https://pypi.org/project/energyplus-toolkit/)
|
|
4
|
+
[](https://pypi.org/project/energyplus-toolkit/)
|
|
5
|
+
[](https://github.com/jmarrec/energyplus-toolkit/actions/workflows/dev.yml)
|
|
6
|
+
|
|
7
|
+
Tools for [EnergyPlus](https://energyplus.net) input files:
|
|
8
|
+
|
|
9
|
+
- parse IDD and IDF files, link each IDF object and field to its IDD definition, and write them back faithfully;
|
|
10
|
+
- reformat IDF and IDD files, and the IDF embedded in EnergyPlus C++ unit tests, from the command line or as
|
|
11
|
+
pre-commit hooks.
|
|
12
|
+
|
|
13
|
+
* GitHub: <https://github.com/jmarrec/energyplus-toolkit>
|
|
14
|
+
* PyPI: <https://pypi.org/project/energyplus-toolkit/>
|
|
15
|
+
|
|
16
|
+
## Installation
|
|
17
|
+
|
|
18
|
+
```bash
|
|
19
|
+
pip install energyplus-toolkit
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
Requires Python 3.11+.
|
|
23
|
+
|
|
24
|
+
For development:
|
|
25
|
+
|
|
26
|
+
```bash
|
|
27
|
+
pip install -e ".[dev,test]" # With the dev tools (pre-commit, black, isort, flake8, mypy) and the tests (pytest)
|
|
28
|
+
pre-commit install
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
## Command line
|
|
32
|
+
|
|
33
|
+
```shell
|
|
34
|
+
# Reformat in place, like black: files and/or folders (searched recursively), in parallel
|
|
35
|
+
energyplus-toolkit format idf --idd Energy+.idd testfiles/
|
|
36
|
+
energyplus-toolkit format idd Energy+.idd
|
|
37
|
+
energyplus-toolkit format unit-test --idd Energy+.idd tst/EnergyPlus/unit
|
|
38
|
+
|
|
39
|
+
# Only look: list the files that would change (exit 1 if any), or print a diff
|
|
40
|
+
energyplus-toolkit format idf --idd Energy+.idd --check testfiles/
|
|
41
|
+
energyplus-toolkit format idf --idd Energy+.idd --diff testfiles/1ZoneUncontrolled.idf
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
Options (see `--help`): `--exclude REGEX`, `-j N` workers, `-q` quiet, `-o OUTPUT` (single file, `-` for stdout),
|
|
45
|
+
and for IDF / unit tests `--leading N` (spaces before object names) and `--keep-integer-reals` (keep `8` instead of
|
|
46
|
+
writing `8.0` in a real field).
|
|
47
|
+
|
|
48
|
+
Exit codes: 0 when done, 1 if `--check` found files to reformat, 123 on error.
|
|
49
|
+
|
|
50
|
+
Content is never lost: a file or block that can't be reformatted safely (unknown object, text outside a field, IMF or
|
|
51
|
+
parametric file, C++ code building the IDF...) is left unchanged, with a warning.
|
|
52
|
+
|
|
53
|
+
## pre-commit hooks
|
|
54
|
+
|
|
55
|
+
```yaml
|
|
56
|
+
- repo: https://github.com/jmarrec/energyplus-toolkit
|
|
57
|
+
rev: v0.1.0
|
|
58
|
+
hooks:
|
|
59
|
+
- id: energyplus-format-idd
|
|
60
|
+
args: [--idd, idd/Energy+.idd.in]
|
|
61
|
+
- id: energyplus-format-idf
|
|
62
|
+
args: [--idd, idd/Energy+.idd.in, -q]
|
|
63
|
+
- id: energyplus-format-unit-test
|
|
64
|
+
args: [--idd, idd/Energy+.idd.in, -q]
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
Each hook needs the IDD to use (`--idd`). For unit tests, put the hook before clang-format: reformatting then
|
|
68
|
+
clang-format is stable.
|
|
69
|
+
|
|
70
|
+
## Library
|
|
71
|
+
|
|
72
|
+
The IDD gives each IDF object and field its definition: type, units, default, choices, extensible groups...
|
|
73
|
+
|
|
74
|
+
```python
|
|
75
|
+
from pathlib import Path
|
|
76
|
+
|
|
77
|
+
from energyplus_toolkit.input.idd.idd_file import IddFile
|
|
78
|
+
from energyplus_toolkit.input.idf.idf_file import IdfFile
|
|
79
|
+
from energyplus_toolkit.input.idf.idf_object import IdfObject
|
|
80
|
+
|
|
81
|
+
idd = IddFile.load(Path("Energy+.idd"))
|
|
82
|
+
|
|
83
|
+
# A whole IDF file: each object is linked to its IDD object
|
|
84
|
+
idf = IdfFile.load("in.idf", idd) # or IdfFile.loads(text, idd)
|
|
85
|
+
for zone in idf.get_objects_by_type("Zone"):
|
|
86
|
+
print(zone.name, zone.getDouble(1), zone.getDouble(1, return_default=True)) # "Z2 None 0.0" if left blank
|
|
87
|
+
idf.save("out.idf", overwrite=True) # or str(idf)
|
|
88
|
+
|
|
89
|
+
# A single object, from its text and its IDD object
|
|
90
|
+
zone = IdfObject.load(idd_object=idd.getObject("Zone"), text="Zone,Z3,90;")
|
|
91
|
+
zone.setDouble(1, 45.0)
|
|
92
|
+
print(zone)
|
|
93
|
+
# Zone,
|
|
94
|
+
# Z3, !- Name
|
|
95
|
+
# 45.0; !- Direction of Relative North {deg}
|
|
96
|
+
|
|
97
|
+
# Or built from scratch, with extensible groups
|
|
98
|
+
branch = IdfObject(idd_object=idd.getObject("Branch"))
|
|
99
|
+
branch.setString(0, "Supply Branch")
|
|
100
|
+
branch.push_extensible_group(["Pump:VariableSpeed", "Pump", "Pump-Inlet", "Pump-Outlet"])
|
|
101
|
+
|
|
102
|
+
# The IDD side
|
|
103
|
+
field = idd.getObject("Zone").fields[1]
|
|
104
|
+
print(field.name, field.properties.type, field.properties.units, field.properties.stringDefault)
|
|
105
|
+
# Direction of Relative North real deg 0
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
Values are validated against the IDD when set (types, choices, bounds), and the IDF is written with its comments
|
|
109
|
+
(`!- Field Name {units}`) and the layout the IDD asks for (`\format`: vertices, compact schedules...).
|
|
110
|
+
|
|
111
|
+
## Layout
|
|
112
|
+
|
|
113
|
+
- `energyplus_toolkit/input`: the EnergyPlus input data model (IDD and IDF objects, fields, their types), read from and
|
|
114
|
+
written to files. It doesn't depend on the tools, so it can become its own package.
|
|
115
|
+
- `energyplus_toolkit/format`: the formatter (parallel runner, C++ unit tests: see `format/cpp/README.md`).
|
|
116
|
+
- `energyplus_toolkit/cli.py`: the `energyplus-toolkit` command.
|
|
@@ -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
|