Skip to content

Commit a67ddfe

Browse files
authored
Merge pull request #76 from SMI-Lab-Inha/dev
chore: bump version to 1.8.0
2 parents 131cc61 + 3c9155b commit a67ddfe

3 files changed

Lines changed: 145 additions & 27 deletions

File tree

‎CHANGELOG.md‎

Lines changed: 143 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -8,34 +8,54 @@ The format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).
88

99
## [Unreleased]
1010

11-
Project-infrastructure round. No public-API change; no numerical
12-
change. Re-license + docs site + governance scaffolding + CI hardening.
13-
14-
### Changed
15-
16-
- **Re-licensed MIT → Apache 2.0.** ``LICENSE`` is the Apache 2.0
17-
text with copyright ``2024-2026 Jae Hoon Seo, Marine Structural
18-
Mechanics and Integrity Lab (SMI Lab), Inha University``;
19-
``pyproject.toml`` classifier and README badge updated; the
20-
bundled ``_examples/`` and ``reference_decks/`` README provenance
21-
notes re-state the new licence. The book-citation reference to
22-
"MIT Press" in ``mooring.py`` is unrelated to project licensing
23-
and is preserved.
24-
- **Upstream-data directories relocated to ``external/``** (issue
25-
raised in static review). ``docs/{BModes, OpenFAST_files, MoorPy,
26-
RAFT, references}`` → ``external/{...}``; the ``docs/`` tree is
27-
now reserved for the Sphinx documentation site. ``.gitignore``,
28-
local development notes, README, RELEASE_CHECKLIST,
29-
every case-study ``run.py``, every visualisation script, the
30-
reference-turbine ``build.py``, and 30 tracked files in total
31-
point at ``external/`` after the rewrite. Integration tests
32-
unchanged behaviourally; they skip when the data is absent.
33-
- **``docs/RELEASE_CHECKLIST.md`` moved to
34-
``https://pybmodes.readthedocs.io/en/latest/release_checklist.html``** to slot into the new Sphinx
35-
developer-guide toctree.
11+
(nothing yet)
12+
13+
## [1.8.0] — 2026-05-21
14+
15+
Multi-phase architecture refactor + project-infrastructure round. No
16+
public-API change; no numerical change. Three threads landed:
17+
18+
- **Phase 1** — re-license (MIT → Apache 2.0), Sphinx documentation
19+
site on Read the Docs, governance + CI hardening, strict mypy /
20+
ruff ratchet, unified ``ParseError`` hierarchy, centralised
21+
numerical options dataclasses.
22+
- **Phase 2** — every ``pybmodes`` CLI subcommand is now a typed
23+
library entry point under :mod:`pybmodes.workflows`; ``cli.py``
24+
shrinks from ~1500 to ~520 lines and is purely
25+
argparse + delegation. Seven new workflow functions and seven
26+
result dataclasses; thirty-nine direct workflow tests.
27+
- **Phase 3** — three biggest source files broken up by concern:
28+
``campbell.py`` (1301 LOC → 7-file ``campbell/`` sub-package),
29+
``mooring.py`` (1202 LOC → 6-file ``mooring/`` sub-package),
30+
``models/tower.py`` private helpers extracted to
31+
``models/_shared.py`` (cross-model) and ``models/_platform.py``
32+
(tower-specific platform-scalar parsers). Every public name
33+
is preserved; existing imports keep working through the
34+
``__init__.py`` re-export layer.
3635

3736
### Added
3837

38+
- **``pybmodes.workflows.*`` typed-result library API** (Phase 2 PRs
39+
B1–B3). Seven entry-points, one per CLI subcommand, each returning
40+
a :class:`WorkflowResult` subclass with ``exit_code`` /
41+
``messages`` / ``errors`` plus the workflow's typed payload:
42+
43+
- :func:`run_validate` → :class:`ValidateResult`
44+
- :func:`run_examples_copy` → :class:`ExamplesResult`
45+
- :func:`run_patch` → :class:`PatchResult` (five mutually-
46+
supportive output modes: default in-place, ``backup``,
47+
``output_dir``, ``dry_run``, ``diff``)
48+
- :func:`run_report` → :class:`ReportResult`
49+
- :func:`run_batch` → :class:`BatchResult`
50+
- :func:`run_campbell` → :class:`CampbellWorkflowResult`
51+
- :func:`run_windio` → :class:`WindioResult` plus
52+
:func:`discover_windio_inputs` returning a
53+
:class:`WindioDiscovery` dataclass.
54+
55+
Lets notebooks and external scripts run the same flows the CLI
56+
uses without ``subprocess`` (the original 0.x workflows-via-stdout
57+
contract is preserved via the slim CLI wrappers).
58+
3959
- **Sphinx documentation site** (``docs/``) hosted on Read the Docs
4060
(``.readthedocs.yaml``). Flat reStructuredText tree — 13 pages:
4161
``index``, ``installation``, ``quickstart``, ``theory``,
@@ -88,6 +108,99 @@ change. Re-license + docs site + governance scaffolding + CI hardening.
88108
sdist, wheel, and cross-install version sanity; uploads the
89109
dist and docs as artifacts. Pre-tag gate that goes beyond the
90110
per-PR CI.
111+
- **Unified :class:`pybmodes.io.ParseError` hierarchy** (Phase 1 PR
112+
A3). Six per-format subclasses
113+
(``BmiParseError``, ``ElastoDynParseError``, ``MoorDynParseError``,
114+
``OutParseError``, ``SubDynParseError``, ``WindIOParseError``)
115+
let library callers catch parse errors precisely. Twenty-nine
116+
regression tests pin hashability and ``__eq__`` semantics
117+
(Codex caught the original ``@dataclass`` shadowing of
118+
``__hash__`` post-merge).
119+
- **Centralised numerical options dataclasses** (Phase 1 PR A1):
120+
:class:`pybmodes.options.SolverOptions`,
121+
:class:`pybmodes.options.FitOptions`,
122+
:class:`pybmodes.options.CheckOptions`. ``frozen=True`` dataclasses
123+
that surface every magic number from ``fem/solver``,
124+
``elastodyn/params``, and ``checks`` as named, defaulted
125+
parameters.
126+
127+
### Changed
128+
129+
- **Re-licensed MIT → Apache 2.0.** ``LICENSE`` is the Apache 2.0
130+
text with copyright ``2024-2026 Jae Hoon Seo, Marine Structural
131+
Mechanics and Integrity Lab (SMI Lab), Inha University``;
132+
``pyproject.toml`` classifier and README badge updated; the
133+
bundled ``_examples/`` and ``reference_decks/`` README provenance
134+
notes re-state the new licence. The book-citation reference to
135+
"MIT Press" in ``mooring.py`` is unrelated to project licensing
136+
and is preserved.
137+
- **Upstream-data directories relocated to ``external/``** (issue
138+
raised in static review). ``docs/{BModes, OpenFAST_files, MoorPy,
139+
RAFT, references}`` → ``external/{...}``; the ``docs/`` tree is
140+
now reserved for the Sphinx documentation site. ``.gitignore``,
141+
local development notes, README, RELEASE_CHECKLIST,
142+
every case-study ``run.py``, every visualisation script, the
143+
reference-turbine ``build.py``, and 30 tracked files in total
144+
point at ``external/`` after the rewrite. Integration tests
145+
unchanged behaviourally; they skip when the data is absent.
146+
- **``docs/RELEASE_CHECKLIST.md`` moved to
147+
``https://pybmodes.readthedocs.io/en/latest/release_checklist.html``** to slot into the new Sphinx
148+
developer-guide toctree.
149+
- **Strict mypy expanded** (Phase 1 PR A2). Five additional modules
150+
joined the strict-typing override list:
151+
``pybmodes.models.tower``, ``pybmodes.models.blade``,
152+
``pybmodes.campbell``, ``pybmodes.mac``, ``pybmodes.io.bmi``,
153+
``pybmodes.options``.
154+
155+
### Refactored
156+
157+
- **CLI subcommands extracted to typed workflow functions** (Phase 2
158+
PRs B1–B3, merged in #69, #71, #72; #70 is the static-review
159+
P3 follow-up to B1). ``cli.py`` shrinks from ~1500 LOC to ~520
160+
LOC and is purely argparse + delegation. Every subcommand
161+
(validate / examples / patch / report / batch / campbell /
162+
windio) is now library-callable with a typed result. CLI flag /
163+
exit-code contract preserved byte-for-byte; the existing CLI
164+
smoke tests (``test_validate.py``, ``test_examples_cli.py``,
165+
``test_batch.py``, ``test_report.py``, ``test_campbell.py``,
166+
``test_windio_cli.py``) pass unchanged. Static-review P3 fix on
167+
PR B1: :func:`pybmodes.workflows.run_examples_copy` now
168+
preserves the accumulated skipped-bundle warning when a later
169+
bundle hits a destination conflict; regression test in
170+
``test_workflows.py`` pins the contract.
171+
- **``pybmodes.campbell`` split into a sub-package** (Phase 3 PR
172+
C1, merged in #73). The 1301-LOC monolith becomes seven files —
173+
``result.py`` (271 LOC, :class:`CampbellResult` dataclass + NPZ
174+
/ CSV serialization), ``_models.py`` (210 LOC, input
175+
dispatcher), ``_classify.py`` (119 LOC, mode-naming
176+
heuristics), ``_mac.py`` (90 LOC, MAC + Hungarian assignment),
177+
``_sweep.py`` (347 LOC, rotor-speed sweep drivers + public
178+
``campbell_sweep``), ``_plot.py`` (393 LOC, engineering-report
179+
diagram). ``__init__.py`` re-exports every public and underscore-
180+
private name existing tests import by name; no test edits
181+
required.
182+
- **``pybmodes.mooring`` split into a sub-package** (Phase 3 PR
183+
C2, merged in #74). 1202-LOC monolith → six files —
184+
``types.py`` (248 LOC, :class:`LineType` / :class:`Point` /
185+
:class:`Line` + :meth:`Line.solve_static`), ``system.py`` (608
186+
LOC, :class:`MooringSystem` + two ``from_*`` parsers),
187+
``_catenary.py`` (113 LOC, residual + analytical Jacobian for
188+
Jonkman 2007 B-1/B-2 + B-7/B-8), ``_rotation.py`` (41 LOC,
189+
3-2-1 Euler primitive), ``_moordyn_parser.py`` (255 LOC,
190+
MoorDyn ``.dat`` section / row tokenisers). Public API
191+
(:class:`LineType`, :class:`Point`, :class:`Line`,
192+
:class:`MooringSystem`) byte-identical via ``__init__.py``
193+
re-exports.
194+
- **``models/tower.py`` private helpers extracted** (Phase 3 PR
195+
C3, merged in #75). ``_run_validation_and_warn`` →
196+
``models/_shared.py`` (cross-model; ``RotatingBlade.from_elastodyn``
197+
was already reaching across, now imports directly).
198+
``_scan_platform_fields`` + ``_platform_inertia_matrix`` →
199+
``models/_platform.py`` (tower-specific). ``tower.py`` ends
200+
at 968 LOC (down from 1083) with all three names re-exported
201+
for back-compat. The :class:`Tower` class stayed together;
202+
a planned mixin-based split was rejected by Plan-agent review
203+
as architecturally hollow.
91204

92205
### Fixed
93206

@@ -104,6 +217,11 @@ change. Re-license + docs site + governance scaffolding + CI hardening.
104217
``axhline``s) keep the original full-axis comb. Backward-compatible
105218
on ``rpm.min() == 0``. Regression test ``test_plot_campbell_blade_
106219
label_anchored_on_curve_for_positive_rpm`` pins the new behaviour.
220+
- **``pybmodes.io.ParseError`` hashability** (PR #68 Codex P2
221+
follow-up). The original ``@dataclass`` decorator on the
222+
``ParseError`` base shadowed ``__hash__`` to ``None``, breaking
223+
``set(exceptions)`` callers. Switched to ``@dataclass(eq=False)``
224+
with 29 regression tests in ``test_io_errors.py``.
107225

108226
## [1.7.0] — 2026-05-18
109227

‎pyproject.toml‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
44

55
[project]
66
name = "pybmodes"
7-
version = "1.7.0"
7+
version = "1.8.0"
88
description = "Python finite-element library for wind turbine blade and tower modal analysis (OpenFAST/ElastoDyn)"
99
readme = "README.md"
1010
license = { file = "LICENSE" }

‎src/pybmodes/__init__.py‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -178,7 +178,7 @@
178178
try:
179179
__version__ = version("pybmodes")
180180
except PackageNotFoundError:
181-
__version__ = "1.7.0-dev"
181+
__version__ = "1.8.0-dev"
182182

183183
__all__ = [
184184
"__version__",

0 commit comments

Comments
 (0)