Skip to content

Commit

Permalink
Allow sinks/sources to have multiple inputs/outputs
Browse files Browse the repository at this point in the history
There was a warning and a comment that having multiple inputs/outputs
for one Sink/Source is unintended but should be possible.
I think we can remove that "strong reccomendation" as it just works.

To not let beginners fall into the trap of having a dangling Sink
or Source, like the old warning also might have prevented, inputs and
outputs are now explicitly named arguments without a default.
  • Loading branch information
p-snft committed Jul 2, 2024
1 parent 5d381b0 commit b516f7e
Show file tree
Hide file tree
Showing 3 changed files with 8 additions and 86 deletions.
24 changes: 4 additions & 20 deletions src/oemof/solph/components/_sink.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,7 @@
SPDX-License-Identifier: MIT
"""
from warnings import warn

from oemof.network import Node
from oemof.tools import debugging


class Sink(Node):
Expand All @@ -27,6 +24,9 @@ class Sink(Node):
label : str
String holding the label of the Sink object.
The label of each object must be unique.
inputs: dict
A dictionary mapping input nodes to corresponding inflows
(i.e. input values).
Examples
--------
Expand All @@ -39,30 +39,14 @@ class Sink(Node):
... label='el_export',
... inputs={bel: solph.flows.Flow()})
Notes
-----
It is theoretically possible to use the Sink object with multiple inputs.
However, we strongly recommend using multiple Sink objects instead.
"""

def __init__(self, label=None, inputs=None, custom_attributes=None):
def __init__(self, label=None, *, inputs, custom_attributes=None):
if inputs is None:
inputs = {}
if custom_attributes is None:
custom_attributes = {}

if len(inputs) != 1:
msg = (
"A Sink is designed to have one input but you provided {0}."
" If this is intended and you know what you are doing you can "
"disable the SuspiciousUsageWarning globally."
)
warn(
msg.format(len(inputs)),
debugging.SuspiciousUsageWarning,
)

super().__init__(
label=label, inputs=inputs, custom_properties=custom_attributes
)
Expand Down
26 changes: 4 additions & 22 deletions src/oemof/solph/components/_source.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,7 @@
SPDX-License-Identifier: MIT
"""

from warnings import warn

from oemof.network import Node
from oemof.tools import debugging


class Source(Node):
Expand All @@ -28,6 +24,9 @@ class Source(Node):
label : str
String holding the label of the Source object.
The label of each object must be unique.
outputs: dict
A dictionary mapping input nodes to corresponding outflows
(i.e. output values).
Examples
--------
Expand All @@ -48,31 +47,14 @@ class Source(Node):
>>> str(pv_plant.outputs[bel].output)
'electricity'
Notes
-----
It is theoretically possible to use the Source object with multiple
outputs. However, we strongly recommend using multiple Source objects
instead.
"""

def __init__(self, label=None, outputs=None, custom_attributes=None):
def __init__(self, label=None, *, outputs, custom_attributes=None):
if outputs is None:
outputs = {}
if custom_attributes is None:
custom_attributes = {}

if len(outputs) != 1:
msg = (
"A Source is designed to have one output but you provided {0}."
" If this is intended and you know what you are doing you can "
"disable the SuspiciousUsageWarning globally."
)
warn(
msg.format(len(outputs)),
debugging.SuspiciousUsageWarning,
)

super().__init__(
label=label, outputs=outputs, custom_properties=custom_attributes
)
Expand Down
44 changes: 0 additions & 44 deletions tests/test_warnings.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,50 +28,6 @@ def warning_fixture():
warnings.simplefilter(action="ignore", category=FutureWarning)


def test_that_the_sink_errors_actually_get_raised(warning_fixture):
"""Sink doesn't warn about potentially erroneous usage."""
look_out = solph.Bus()
with pytest.raises(
TypeError, match="got an unexpected keyword argument 'outputs'"
):
solph.components.Sink(label="test_sink", outputs={look_out: "A typo!"})

msg = (
"A Sink is designed to have one input but you provided 0."
" If this is intended and you know what you are doing you can "
"disable the SuspiciousUsageWarning globally."
)
with warnings.catch_warnings(record=True) as w:
solph.components.Sink(
label="no input",
)
assert len(w) == 1
assert msg in str(w[-1].message)


def test_that_the_source_warnings_actually_get_raised(warning_fixture):
"""Source doesn't warn about potentially erroneous usage."""
look_out = solph.Bus()
with pytest.raises(
TypeError, match="got an unexpected keyword argument 'inputs'"
):
solph.components.Source(
label="test_source", inputs={look_out: "A typo!"}
)

msg = (
"A Source is designed to have one output but you provided 0."
" If this is intended and you know what you are doing you can "
"disable the SuspiciousUsageWarning globally."
)
with warnings.catch_warnings(record=True) as w:
solph.components.Source(
label="no output",
)
assert len(w) == 1
assert msg in str(w[-1].message)


def test_that_the_converter_warnings_actually_get_raised(warning_fixture):
"""Converter doesn't warn about potentially erroneous usage."""
look_out = solph.Bus()
Expand Down

0 comments on commit b516f7e

Please sign in to comment.