Skip to content

Register models with a @register decorator instead of a hardcoded dictionary - #902

Merged
johnjasa merged 5 commits into
NatLabRockies:developfrom
johnjasa:issue-901-model-registration
Oct 7, 2026
Merged

johnjasa merged 5 commits into
NatLabRockies:developfrom
johnjasa:issue-901-model-registration

Conversation

@johnjasa

@johnjasa johnjasa commented Oct 2, 2026

Copy link
Copy Markdown
Collaborator

Register models with a @register decorator instead of a hardcoded dictionary

Models are now registered by decorating the class, so adding a model no longer requires editing supported_models.py. Model modules are still imported lazily.

from h2integrate.core.supported_models import register


@register  # registered under the class name
class MyPerformanceModel(PerformanceModelBaseClass): ...


@register(name="cable", no_cost=True)  # optional name and flags
class CablePerformanceModel(om.ExplicitComponent): ...
  1. Added a register marker decorator with optional name, no_cost, and no_replacement_schedule arguments.
  2. supported_models.py now builds supported_models, no_cost_models, and no_replacement_schedule_models by scanning the package source for @register. Classes are imported on first lookup, and duplicate names raise a ValueError.
  3. Decorated all 148 previously registered classes and removed the hardcoded dictionary. Names and resolved classes are unchanged.
  4. Updated the developer guide, related docs, and the PR template checklist.

Section 1: Type of Contribution

  • Feature Enhancement
    • Framework
    • New Model
    • Updated Model
    • Tools/Utilities
    • Other (please describe):
  • Bug Fix
  • Documentation Update
  • CI Changes
  • Other (please describe):

Section 2: Draft PR Checklist

  • Open draft PR
  • Describe the feature that will be added
  • Fill out TODO list steps
  • Describe requested feedback from reviewers on draft PR
  • Complete Section 8: New Model Checklist (if applicable)

TODO:

N/A

Type of Reviewer Feedback Requested (on Draft PR)

Structural feedback: N/A

Implementation feedback: N/A

Other feedback: N/A

Section 3: General PR Checklist

  • PR description thoroughly describes the new feature, bug fix, etc.
  • Added tests for new functionality or bug fixes
  • Tests pass (If not, and this is expected, please elaborate in the Section 6: Test Results)
  • Documentation
    • Docstrings are up-to-date
    • Related docs/ files are up-to-date, or added when necessary
    • Documentation has been rebuilt successfully
    • Examples have been updated (if applicable)
  • CHANGELOG.md
    • At least one complete sentence has been provided to describe the changes made in this PR
    • After the above, a hyperlink has been provided to the PR using the following format:
      "A complete thought. [PR XYZ]((https://github.com/NatLabRockies/H2Integrate/pull/XYZ)", where
      XYZ should be replaced with the actual number.

Section 4: Related Issues

Resolves #901

Section 5: Impacted Areas of the Software

Section 5.1: New Files

  • h2integrate/core/test/test_supported_models.py
    • Tests lazy lookup, the name argument, and the flag sets.

Section 5.2: Modified Files

  • h2integrate/core/supported_models.py
    • Replaced the hardcoded dictionary with the register decorator and a source scan (275 to 72 lines).
  • h2integrate/{control,converters,demand,feedstocks,finances,resource,storage,transporters}/**/*.py (103 files)
    • Added @register to each previously registered model class.
  • docs/generate_model_overview.py
    • Updated the generated note on how to add or rename a model.
  • pyproject.toml
    • Removed the E501 ignore for supported_models.py, which no longer has long lines.
  • .github/PULL_REQUEST_TEMPLATE.md
    • Updated the new model checklist to use @register.

Section 6: Additional Supporting Information

  • I had to do some special scanning logic to get the lazy imports working with the decorator. A normal decorator registry would require importing every model module up front, which takes about 10 s on Windows (pyomo, ard, rex, wombat, ProFAST). The text scan adds about 0.2 s to import h2integrate.
  • Because the decorator is only a marker, @register must be at column 0, directly above the class line, with literal arguments.

Section 7: Test Results, if applicable

Runs locally well!

Section 8 (Optional): New Model Checklist

N/A

@johnjasa
johnjasa requested a review from RHammond2 October 2, 2026 02:57
@johnjasa
johnjasa marked this pull request as draft October 5, 2026 19:28
@johnjasa
johnjasa marked this pull request as ready for review October 5, 2026 19:28

@RHammond2 RHammond2 left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Really great riffing on #901! I failed to consider the lazy import style that supported_models uses when thinking through the solution, so your implementation felt bizarre until it finally clicked. Great stuff!

text = path.read_text(encoding="utf-8")
if "@register" not in text or "test" in path.relative_to(_PACKAGE_DIR).parts:
continue
module = ".".join(path.relative_to(_PACKAGE_DIR.parent).with_suffix("").parts)

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Love to see some slick Path logic!

@johnjasa
johnjasa enabled auto-merge October 7, 2026 21:51
@johnjasa
johnjasa merged commit c87d9b8 into NatLabRockies:develop Oct 7, 2026
12 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants