Skip to content

Add FlowContainer for inputs/outputs - #587

Merged
FBumann merged 5 commits into
mainfrom
feature/containers
Jan 23, 2026
Merged

Add FlowContainer for inputs/outputs#587
FBumann merged 5 commits into
mainfrom
feature/containers

Conversation

@FBumann

@FBumannFBumann commented Jan 23, 2026

Copy link
Copy Markdown
Member

Summary

Replaces list[Flow] with FlowContainer for inputs, outputs, and flows attributes. Provides dual access by index (inputs[0]) or label (inputs['Q_th']).

Breaking Change

Use .values() for flow iteration: for flow in component.inputs.values():

Summary by CodeRabbit

  • New Features

    • Introduced FlowContainer for flexible access to component and bus flows by index or label (e.g., inputs[0] or inputs['Q_th'])
    • Added new flows property to components and buses for unified access to both inputs and outputs
  • Refactor

    • Updated internal flow collection handling to use dict-based containers for improved access patterns

✏️ Tip: You can customize this high-level summary in your review settings.

…s done:
Summary
1. Created FlowContainer Class (structure.py)
- Added FlowContainer class that extends ContainerMixin
- Uses flow.label_full as the key (e.g., 'Boiler(Q_th)')
- Supports index-based access: inputs[0]
- Supports label-based access: inputs['Boiler(Q_th)']
- Added __add__ method to ContainerMixin for concatenation
2. Updated Component Class (elements.py)
- Changed inputs and outputs from list[Flow] to FlowContainer
- Modified __init__ to accept both list[Flow] and dict[str, Flow] (for deserialization)
- Updated _check_unique_flow_labels() and _connect_flows() to accept lists as parameters
- FlowContainers are created after connecting flows (so label_full is correct)
3. Updated Bus Class (elements.py)
- Changed inputs and outputs from list[Flow] to FlowContainer
4. Updated Iteration Patterns
All iteration patterns were updated from:
- for flow in self.inputs: → for flow in self.inputs.values():
- for flow in self.inputs + self.outputs: → for flow in (self.inputs + self.outputs).values():
Files updated:
- elements.py (Component, Bus, BusModel, ComponentModel)
- components.py (TransmissionModel, LinearConverterModel)
- flow_system.py (flow population and network connection)
- io.py (format_flow_details)
- statistics_accessor.py (various plotting methods)
- tests/deprecated/test_integration.py
Usage Examples
boiler = Boiler(label='Boiler', inputs=[Flow('Q_th', bus=heat_bus)])
# Both access methods work
assert boiler.inputs[0] == boiler.inputs['Boiler(Q_th)']
assert len(boiler.inputs) == 1
# Iteration requires .values()
for flow in boiler.inputs.values():
print(flow.label_full)
# Concatenation works
all_flows = boiler.inputs + boiler.outputs
for flow in all_flows.values():
print(flow.label)
All 1570 tests passed.
 Added all_flows property to Component and Bus classes using itertools.chain:
@Property
def all_flows(self) -> Iterator[Flow]:
"""Iterate over all flows (inputs and outputs) without creating intermediate containers."""
return chain(self.inputs.values(), self.outputs.values())
Performance Improvement
┌─────────┬──────────────────────────────┬───────────────────────┐
│ Pattern │ Before │ After │
├─────────┼──────────────────────────────┼───────────────────────┤
│ Memory │ O(n) - creates new container │ O(1) - iterator only │
├─────────┼──────────────────────────────┼───────────────────────┤
│ Time │ O(n) - copies all elements │ O(1) - lazy iteration │
└─────────┴──────────────────────────────┴───────────────────────┘
Usage
# Efficient iteration (no allocation)
for flow in component.all_flows:
...
# When you need a list (e.g., reusing multiple times)
all_flows = list(component.all_flows)
# Container concatenation still available when needed
combined = component.inputs + component.outputs # Creates new FlowContainer
Files Updated
- elements.py - Added property, updated 8 iteration patterns
- components.py - Updated 1 pattern
- flow_system.py - Updated 3 patterns
- statistics_accessor.py - Updated 1 pattern
All 1570 tests pass.
 1. FlowContainer now supports short-label access
When all flows in a container belong to the same component, you can access by short label:
# Both work for component.inputs, component.outputs, and component.flows:
component.inputs['Boiler(Q_th)'] # Full label
component.inputs['Q_th'] # Short label ✓
# The `in` operator also supports short labels:
if 'Q_th' in component.flows: # Works!
...
2. Component.flows is now a FlowContainer (cached property)
# Before (dict keyed by short label):
component.flows: dict[str, Flow]
# After (FlowContainer with full/short label access):
component.flows: FlowContainer # cached_property
API Summary
┌─────────────────────┬──────────────────────────────────────┐
│ Access Pattern │ Example │
├─────────────────────┼──────────────────────────────────────┤
│ Full label │ component.flows['Boiler(Q_th)'] │
├─────────────────────┼──────────────────────────────────────┤
│ Short label │ component.flows['Q_th'] │
├─────────────────────┼──────────────────────────────────────┤
│ Index │ component.flows[0] │
├─────────────────────┼──────────────────────────────────────┤
│ Membership │ 'Q_th' in component.flows │
├─────────────────────┼──────────────────────────────────────┤
│ Iteration │ for flow in component.flows.values() │
├─────────────────────┼──────────────────────────────────────┤
│ Efficient iteration │ for flow in component.all_flows │
└─────────────────────┴──────────────────────────────────────┘
Note: Short-label access only works when all flows in the container share the same component (which is always true for component.inputs,
component.outputs, and component.flows).
@coderabbitai

coderabbitaiBot commented Jan 23, 2026

Copy link
Copy Markdown
Contributor

Caution

Review failed

The pull request is closed.

📝 Walkthrough

Walkthrough

Unifies flow collections by introducing FlowContainer and replacing list-based inputs + outputs patterns with container-based access (e.g., .flows.values() / .inputs.values() / .outputs.values()), updating component/bus initialization, topology wiring, modeling, IO, statistics, and tests accordingly.

Changes

Cohort / File(s)Summary
Flow container core
flixopt/structure.py
Added FlowContainer supporting index/label access and improved membership; added ContainerMixin.__add__ to concatenate containers.
Component & Bus declarations
flixopt/elements.py
Component.__init__ accepts list or dict for inputs/outputs; new _connect_flows, flows (FlowContainer) and all_flows properties; Bus updated to expose flows/all_flows.
Flow system wiring
flixopt/flow_system.py
Replace iterations over inputs + outputs with comp.flows.values(); bus wiring switched from list appends to set .add() for bus.inputs/bus.outputs; updated topology/linking logic.
Models updated
flixopt/components.py
TransmissionModel and LinearConverterModel updated to iterate/link over flow containers (.flows.values() / .inputs.values() / .outputs.values()) when building constraints.
I/O and statistics
flixopt/io.py, flixopt/statistics_accessor.py
Iteration and labeling logic changed to use .values() on inputs/outputs and component/bus flow containers for plotting and effect-share calculations.
Tests
tests/deprecated/test_integration.py
Adjusted test setup to iterate merged flow containers via .values() when building flow mappings.
Changelog
CHANGELOG.md
Documented FlowContainer introduction and flow-access API changes.

Sequence Diagram(s)

(omitted)

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

Suggested labels

v3.0.0

Poem

🐇 I hop through flows both short and long,

containers sing a tidy song,
indices, labels, all in line,
components link and models shine—
a little refactor, neat and strong.

🚥 Pre-merge checks | ✅ 1 | ❌ 2
❌ Failed checks (2 warnings)
Check nameStatusExplanationResolution
Docstring Coverage⚠️ WarningDocstring coverage is 66.67% which is insufficient. The required threshold is 80.00%.Write docstrings for the functions missing them to satisfy the coverage threshold.
Description check⚠️ WarningThe description is incomplete. It lacks the required template sections including Type of Change, Related Issues, Testing checklist, and the complete Checklist items.Use the repository's pull request template and complete all required sections including Type of Change checkboxes, Related Issues, Testing status, and full Checklist.
✅ Passed checks (1 passed)
Check nameStatusExplanation
Title check✅ PassedThe title accurately summarizes the main change: introducing FlowContainer for inputs/outputs attributes to provide dual access patterns.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
  • 📝 Generate docstrings

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@FBumannFBumann changed the title Feature/containersAdd FlowContainer for inputs/outputs with dual access (index + label)Jan 23, 2026
@FBumann

Copy link
Copy Markdown
MemberAuthor

@coderabbitai review

@coderabbitai

Copy link
Copy Markdown
Contributor
✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@FBumannFBumann changed the title Add FlowContainer for inputs/outputs with dual access (index + label)Add FlowContainer for inputs/outputsJan 23, 2026
@FBumann
FBumann marked this pull request as ready for review January 23, 2026 14:45
@FBumann
FBumann merged commit 8e8fe5c into mainJan 23, 2026
7 of 8 checks passed
Sign up for freeto 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.

1 participant

@FBumann