Skip to content

Commit 5499ab9

Browse files
committed
Fix #4
1 parent 1450e86 commit 5499ab9

File tree

4 files changed

+41
-10
lines changed

4 files changed

+41
-10
lines changed

README.md

+6-1
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,7 @@ To create custom allocation functions which apply a single allocation factor to
8888

8989
* edge_data (dict): Data on functional edge
9090
* node: An instance of `multifunctional.MaybeMultifunctionalProcess`
91+
* strategy_label: An optional string to label the allocation strategy used
9192

9293
The custom function should return a number.
9394

@@ -106,7 +107,11 @@ def allocation_factor(edge_data: dict, node: mf.MaybeMultifunctionalProcess) ->
106107
else:
107108
return 7
108109

109-
mf.allocation_strategies['silly'] = partial(mf.generic_allocation, func=allocation_factor)
110+
mf.allocation_strategies['silly'] = partial(
111+
mf.generic_allocation,
112+
func=allocation_factor,
113+
strategy_label="something silly"
114+
)
110115
```
111116

112117
### Other custom allocation functions

multifunctional/allocation.py

+15-6
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,24 @@
11
from copy import deepcopy
22
from functools import partial
3-
from typing import Callable, List
3+
from typing import Callable, List, Optional
44
from uuid import uuid4
55

6+
from bw2data import get_node
7+
from bw2data.errors import UnknownObject
68
from bw2io.utils import rescale_exchange
79
from loguru import logger
8-
from bw2data.errors import UnknownObject
9-
from bw2data import get_node
1010

1111
from .node_classes import (
1212
MaybeMultifunctionalProcess,
1313
ReadOnlyProcessWithReferenceProduct,
1414
)
1515

1616

17-
def generic_allocation(act: MaybeMultifunctionalProcess, func: Callable) -> List[dict]:
17+
def generic_allocation(
18+
act: MaybeMultifunctionalProcess,
19+
func: Callable,
20+
strategy_label: Optional[str] = None,
21+
) -> List[dict]:
1822
"""Allocation by single allocation factor generated by `func`.
1923
2024
Allocation amount is edge amount times function(edge_data, act) divided by sum of all edge
@@ -74,22 +78,26 @@ def generic_allocation(act: MaybeMultifunctionalProcess, func: Callable) -> List
7478
)
7579

7680
try:
77-
assert not exc.get('mf_artificial_code')
81+
assert not exc.get("mf_artificial_code")
7882
product = get_node(database=exc["input"][0], code=exc["input"][1])
7983
except (KeyError, UnknownObject, AssertionError):
8084
product = None
8185

8286
allocated_process = deepcopy(act._data)
8387
if "id" in allocated_process:
8488
del allocated_process["id"]
89+
if strategy_label:
90+
allocated_process["mf_strategy_label"] = strategy_label
8591
allocated_process["code"] = process_code
8692
allocated_process["multifunctional_parent_id"] = act.id
8793
allocated_process["type"] = "readonly_process"
8894

8995
if "name" in exc:
9096
allocated_process["reference product"] = exc["name"]
9197
elif product:
92-
allocated_process["reference product"] = product.get("name", "(unnamed product)")
98+
allocated_process["reference product"] = product.get(
99+
"name", "(unnamed product)"
100+
)
93101
else:
94102
allocated_process["reference product"] = "(unnamed)"
95103

@@ -141,6 +149,7 @@ def property_allocation(property_label: str) -> Callable:
141149
func=partial(
142150
get_allocation_factor_from_property, property_label=property_label
143151
),
152+
strategy_label=f"property allocation by '{property_label}'"
144153
)
145154

146155

tests/test_allocation.py

+11
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,17 @@ def test_without_allocation(basic):
118118
assert nodes[1][key] == value
119119

120120

121+
def test_price_allocation_strategy_label(basic):
122+
basic.metadata["default_allocation"] = "price"
123+
bd.get_node(code="1").allocate()
124+
nodes = sorted(basic, key=lambda x: (x["name"], x.get("reference product", "")))
125+
126+
assert not nodes[0].get("mf_strategy_label")
127+
assert not nodes[1].get("mf_strategy_label")
128+
assert nodes[2].get("mf_strategy_label") == "property allocation by 'price'"
129+
assert nodes[3].get("mf_strategy_label") == "property allocation by 'price'"
130+
131+
121132
def test_price_allocation(basic):
122133
basic.metadata["default_allocation"] = "price"
123134
bd.get_node(code="1").allocate()

tests/test_allocation_with_products.py

+9-3
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,9 @@
99

1010

1111
def check_products_allocation_results(factor_1, factor_2, database):
12-
nodes = sorted(database, key=lambda x: (x["name"], x.get("reference product", ""), x["type"]))
12+
nodes = sorted(
13+
database, key=lambda x: (x["name"], x.get("reference product", ""), x["type"])
14+
)
1315

1416
assert isinstance(nodes[0], MaybeMultifunctionalProcess)
1517
assert nodes[0]["name"] == "first product"
@@ -105,7 +107,9 @@ def check_products_allocation_results(factor_1, factor_2, database):
105107

106108

107109
def test_without_allocation(products):
108-
nodes = sorted(products, key=lambda x: (x["name"], x.get("reference product", ""), x["type"]))
110+
nodes = sorted(
111+
products, key=lambda x: (x["name"], x.get("reference product", ""), x["type"])
112+
)
109113

110114
assert len(nodes) == 3
111115

@@ -162,7 +166,9 @@ def test_allocation_uses_existing(products):
162166
def test_allocation_already_allocated(products):
163167
products.metadata["default_allocation"] = "price"
164168
bd.get_node(code="1").allocate()
165-
node = sorted(products, key=lambda x: (x["name"], x.get("reference product", "")))[3]
169+
node = sorted(products, key=lambda x: (x["name"], x.get("reference product", "")))[
170+
3
171+
]
166172

167173
assert generic_allocation(node, None) == []
168174

0 commit comments

Comments
 (0)