Skip to content

Add generic helpers for parsing ranges and use for years and availabilities#1287

Closed
alexdewar wants to merge 6 commits into
mainfrom
availability-range-syntax
Closed

Add generic helpers for parsing ranges and use for years and availabilities#1287
alexdewar wants to merge 6 commits into
mainfrom
availability-range-syntax

Conversation

@alexdewar
Copy link
Copy Markdown
Member

Description

There are currently two contexts in which we allow users to enter values with a range-like syntax in input files: for years and availabilities. There are also some other places where we may want to use the same syntax in future (e.g., #143, #1106).

There are some small inconsistencies between the way the syntax works with availabilities and years, notably in that you cannot express an availability range where the lower and upper bounds are the same with a single value (i.e. you have to write 0.5..0.5 rather than 0.5).

I think it makes sense to have generic helper functions for this and to use them everywhere we need this syntax, for the sake of consistency and maintainability, so this is what I've done. I've tried to to keep things mostly as they were before, but there are a few behavioural changes:

  • You can now use a single value for availabilities, as mentioned (Allow users to enter single value for availability limits where upper and lower bounds are the same #1183)
  • Ranges with lower and upper bounds both omitted (i.e. ..) aren't allowed (I thought it was too confusing for users). We could let users write this as all for all ranges as we do for year ranges, but I haven't done this yet.
  • You can now have year ranges separated by semicolons if you want (e.g. 1990..1999;2010..2019). It's not that I imagine this feature will be widely used, but I don't think it's unclear to write things this way, and it made sense to write the code this way.

For year ranges, we need to be able to specify that the default lower and upper bounds are different from the min and max permissible values (which are actually zero and u32::MAX, so not limits at all), because of #846. We can remove the extra helper if we ever sort #846 (maybe I should let Copilot have a go...).

Unrelated change: I also moved year.rs into src/input/, as its functionality is only used inside input and its submodules.

Closes #1183.

Type of change

  • Bug fix (non-breaking change to fix an issue)
  • New feature (non-breaking change to add functionality)
  • Refactoring (non-breaking, non-functional change to improve maintainability)
  • Optimization (non-breaking change to speed up the code)
  • Breaking change (whatever its nature)
  • Documentation (improve or add documentation)

Key checklist

  • All tests pass: $ cargo test
  • The documentation builds and looks OK: $ cargo doc
  • Update release notes for the latest release if this PR adds a new feature or fixes a bug
    present in the previous release

Further checks

  • Code is commented, particularly in hard-to-understand areas
  • Tests added that prove fix is effective or that feature works

Copilot AI review requested due to automatic review settings May 14, 2026 09:45
@codecov
Copy link
Copy Markdown

codecov Bot commented May 14, 2026

Codecov Report

❌ Patch coverage is 98.11321% with 2 lines in your changes missing coverage. Please review.
✅ Project coverage is 89.49%. Comparing base (0af4399) to head (450cc51).
⚠️ Report is 1 commits behind head on main.

Files with missing lines Patch % Lines
src/input/process/availability.rs 50.00% 0 Missing and 1 partial ⚠️
src/input/range.rs 97.87% 0 Missing and 1 partial ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #1287      +/-   ##
==========================================
+ Coverage   89.46%   89.49%   +0.03%     
==========================================
  Files          57       58       +1     
  Lines        8361     8389      +28     
  Branches     8361     8389      +28     
==========================================
+ Hits         7480     7508      +28     
  Misses        581      581              
  Partials      300      300              

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR refactors range-like input parsing into reusable helpers and applies them to year and availability parsing, making availability limits accept a single fixed value and moving year parsing under the input module.

Changes:

  • Added generic range parsing helpers and new input-local year parsing.
  • Updated availability parsing to use the shared range parser.
  • Updated imports after moving year parsing from src/year.rs to src/input/year.rs.

Reviewed changes

Copilot reviewed 15 out of 15 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
Cargo.toml Enables derive_more support for FromStr.
src/units.rs Adds FromStr support to unit wrapper types.
src/lib.rs Removes the old public year module export.
src/year.rs Removes the old standalone year parser.
src/input.rs Registers range/year input modules and adds sorted-range helper.
src/input/range.rs Adds generic inclusive range parsing helpers.
src/input/year.rs Adds input-scoped year range parsing implementation and tests.
src/input/process/availability.rs Switches availability limit parsing to the shared range parser.
src/input/process/flow.rs Updates year parser import path.
src/input/process/investment_constraints.rs Updates year parser import path.
src/input/process/parameter.rs Updates year parser import path.
src/input/commodity/levy.rs Updates year parser import path.
src/input/agent/* Updates year parser import paths in agent input readers.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread src/input/year.rs
Comment on lines +36 to +38
/// If `valid_years` is empty, unsorted or contains duplicates.
pub fn parse_year_str(s: &str, valid_years: &[u32]) -> Result<Vec<u32>> {
assert!(!valid_years.is_empty(), "`valid_years` cannot be empty");
Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

I think this is the correct behaviour. valid_years should already have been validated by the caller and, if it hasn't been, then that's a coding bug, so panicking is appropriate.

Comment thread src/input/range.rs Outdated
Comment thread src/input/process/availability.rs
@alexdewar alexdewar force-pushed the availability-range-syntax branch from 9c65d45 to baff99f Compare May 14, 2026 09:53
Copy link
Copy Markdown
Collaborator

@tsmbland tsmbland left a comment

Choose a reason for hiding this comment

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

I was never a fan of #1183 for reasons I tried to outline in the issue. If we're doing this then we need to make this SUPER clear in the documentation, otherwise I can almost guarantee that someone will fall into this trap

@alexdewar
Copy link
Copy Markdown
Member Author

@tsmbland Would you be happy with a solution where we don't do #1183, but keep the refactoring? If so, I'll have a go at reworking this.

@tsmbland
Copy link
Copy Markdown
Collaborator

@tsmbland Would you be happy with a solution where we don't do #1183, but keep the refactoring? If so, I'll have a go at reworking this.

Absolutely!

@alexdewar
Copy link
Copy Markdown
Member Author

@tsmbland Would you be happy with a solution where we don't do #1183, but keep the refactoring? If so, I'll have a go at reworking this.

Absolutely!

Cool. In that case, I'll close this PR and have another go then.

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.

Allow users to enter single value for availability limits where upper and lower bounds are the same

3 participants