Skip to content

Commit 22bfdb9

Browse files
committed
Linting
1 parent 8786f49 commit 22bfdb9

17 files changed

+78
-171
lines changed

multifunctional/__init__.py

Lines changed: 5 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -23,25 +23,19 @@
2323
logger.disable("multifunctional")
2424

2525
from bw2data import labels
26-
from bw2data.subclass_mapping import (
27-
DATABASE_BACKEND_MAPPING,
28-
NODE_PROCESS_CLASS_MAPPING,
29-
)
26+
from bw2data.subclass_mapping import DATABASE_BACKEND_MAPPING, NODE_PROCESS_CLASS_MAPPING
3027

3128
from .allocation import allocation_strategies, generic_allocation, property_allocation
32-
from .database import MultifunctionalDatabase
33-
from .node_classes import (
34-
MaybeMultifunctionalProcess,
35-
ReadOnlyProcessWithReferenceProduct,
36-
)
37-
from .node_dispatch import multifunctional_node_dispatcher
38-
from .utils import allocation_before_writing
3929
from .custom_allocation import (
4030
add_custom_property_allocation_to_project,
4131
check_property_for_allocation,
4232
check_property_for_process_allocation,
4333
list_available_properties,
4434
)
35+
from .database import MultifunctionalDatabase
36+
from .node_classes import MaybeMultifunctionalProcess, ReadOnlyProcessWithReferenceProduct
37+
from .node_dispatch import multifunctional_node_dispatcher
38+
from .utils import allocation_before_writing
4539

4640
DATABASE_BACKEND_MAPPING["multifunctional"] = MultifunctionalDatabase
4741
NODE_PROCESS_CLASS_MAPPING["multifunctional"] = multifunctional_node_dispatcher

multifunctional/allocation.py

Lines changed: 6 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -22,9 +22,7 @@ def generic_allocation(
2222
act: Union[dict, Activity],
2323
func: Callable,
2424
strategy_label: Optional[str] = None,
25-
supplemental_functions: Optional[List[Callable]] = [
26-
add_product_node_properties_to_exchange
27-
],
25+
supplemental_functions: Optional[List[Callable]] = [add_product_node_properties_to_exchange],
2826
) -> List[dict]:
2927
"""Allocation by single allocation factor generated by `func`.
3028
@@ -70,14 +68,6 @@ def generic_allocation(
7068
del original_exc["properties"][key]
7169
del original_exc["__mf__properties_from_product"]
7270

73-
# if not factor:
74-
# # Functional product of multifunctional process, but with allocation factor of zero
75-
# # We need to link to *something*, so link to original multifunctional process to avoid
76-
# # unlinked exchanges
77-
# if not original_exc.get("input"):
78-
# original_exc["input"] = (act["database"], act["code"])
79-
# continue
80-
8171
logger.debug(
8272
"Using allocation factor {f} for functional edge {e} on activity {a}",
8373
f=factor,
@@ -122,9 +112,7 @@ def generic_allocation(
122112
if original_exc["mf_manual_input_product"]:
123113
# Get product name and unit attributes from the separate node, if available
124114
try:
125-
product = get_node(
126-
database=new_exc["input"][0], code=new_exc["input"][1]
127-
)
115+
product = get_node(database=new_exc["input"][0], code=new_exc["input"][1])
128116
except UnknownObject:
129117
# Try using attributes stored on the edge
130118
# Might not work, but better than trying to give access to whole raw database
@@ -137,21 +125,18 @@ def generic_allocation(
137125
if "id" in allocated_process:
138126
del allocated_process["id"]
139127
if strategy_label:
140-
allocated_process["mf_strategy_label"] = act["mf_strategy_label"] = (
141-
strategy_label
142-
)
128+
allocated_process["mf_strategy_label"] = act["mf_strategy_label"] = strategy_label
143129
allocated_process["code"] = process_code
144130
allocated_process["mf_parent_key"] = (act["database"], act["code"])
131+
# Used to filter out previous read only processes
145132
allocated_process["type"] = "readonly_process"
146133
allocated_process["production amount"] = original_exc["amount"]
147134
if product:
148135
allocated_process["reference product"] = product.get("name", "(unknown)")
149136
allocated_process["unit"] = product.get("unit", "(unknown)")
150137
else:
151138
allocated_process["reference product"] = new_exc.get("name", "(unknown)")
152-
allocated_process["unit"] = new_exc.get("unit") or act.get(
153-
"unit", "(unknown)"
154-
)
139+
allocated_process["unit"] = new_exc.get("unit") or act.get("unit", "(unknown)")
155140
allocated_process["exchanges"] = [new_exc]
156141

157142
for other in filter(lambda x: not x.get("functional"), act["exchanges"]):
@@ -205,7 +190,5 @@ def property_allocation(
205190
"manual_allocation", normalize_by_production_amount=False
206191
),
207192
"mass": property_allocation("mass"),
208-
"equal": partial(
209-
generic_allocation, func=lambda x, y: 1.0, strategy_label="equal_allocation"
210-
),
193+
"equal": partial(generic_allocation, func=lambda x, y: 1.0, strategy_label="equal_allocation"),
211194
}

multifunctional/custom_allocation.py

Lines changed: 6 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
from dataclasses import dataclass
44
from enum import Enum
55
from numbers import Number
6-
from typing import List, Union, Optional
6+
from typing import List, Optional, Union
77

88
from blinker import signal
99
from bw2data import Database, databases
@@ -65,9 +65,7 @@ def list_available_properties(database_label: str, target_process: Optional[Node
6565
results = []
6666
all_properties = set()
6767

68-
for ds in filter(
69-
lambda x: x["type"] == "multifunctional", Database(database_label)
70-
):
68+
for ds in filter(lambda x: x["type"] == "multifunctional", Database(database_label)):
7169
for edge in filter(lambda x: x.get("functional"), ds.exchanges()):
7270
for key in _get_unified_properties(edge):
7371
all_properties.add(key)
@@ -110,15 +108,12 @@ def check_property_for_process_allocation(
110108
if messages is None:
111109
messages = []
112110

113-
if process['type'] != "multifunctional":
111+
if process["type"] != "multifunctional":
114112
return True
115113

116114
for edge in filter(lambda x: x.get("functional"), process.exchanges()):
117115
properties = _get_unified_properties(edge)
118-
if (
119-
property_label not in properties
120-
and edge.input["type"] != "readonly_process"
121-
):
116+
if property_label not in properties and edge.input["type"] != "readonly_process":
122117
messages.append(
123118
PropertyMessage(
124119
level=logging.WARNING,
@@ -260,12 +255,8 @@ def update_allocation_strategies_on_project_change(
260255
for obsolete in set(allocation_strategies).difference(DEFAULT_ALLOCATIONS):
261256
del allocation_strategies[obsolete]
262257

263-
for key, value in project_dataset.data.get(
264-
"multifunctional.custom_allocations", {}
265-
).items():
258+
for key, value in project_dataset.data.get("multifunctional.custom_allocations", {}).items():
266259
allocation_strategies[key] = property_allocation(**value)
267260

268261

269-
signal("bw2data.project_changed").connect(
270-
update_allocation_strategies_on_project_change
271-
)
262+
signal("bw2data.project_changed").connect(update_allocation_strategies_on_project_change)

multifunctional/node_classes.py

Lines changed: 13 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,11 @@
77

88
from .edge_classes import ReadOnlyExchanges
99
from .errors import NoAllocationNeeded
10-
from .utils import product_as_process_name, update_datasets_from_allocation_results
10+
from .utils import (
11+
product_as_process_name,
12+
set_correct_process_type,
13+
update_datasets_from_allocation_results,
14+
)
1115

1216

1317
class BaseMultifunctionalNode(Activity):
@@ -63,9 +67,7 @@ def allocate(
6367
"Can't find `default_allocation` in input arguments, or process/database metadata."
6468
)
6569
if strategy_label not in allocation_strategies:
66-
raise KeyError(
67-
f"Given strategy label {strategy_label} not in `allocation_strategies`"
68-
)
70+
raise KeyError(f"Given strategy label {strategy_label} not in `allocation_strategies`")
6971

7072
logger.debug(
7173
"Allocating {p} (id: {i}) with strategy {s}",
@@ -126,46 +128,32 @@ def delete(self):
126128

127129
def exchanges(self, exchanges_class=None):
128130
if exchanges_class is not None:
129-
warnings.warn(
130-
"`exchanges_class` argument ignored; must be `ReadOnlyExchanges`"
131-
)
131+
warnings.warn("`exchanges_class` argument ignored; must be `ReadOnlyExchanges`")
132132
return super().exchanges(exchanges_class=ReadOnlyExchanges)
133133

134134
def technosphere(self, exchanges_class=None):
135135
if exchanges_class is not None:
136-
warnings.warn(
137-
"`exchanges_class` argument ignored; must be `ReadOnlyExchanges`"
138-
)
136+
warnings.warn("`exchanges_class` argument ignored; must be `ReadOnlyExchanges`")
139137
return super().technosphere(exchanges_class=ReadOnlyExchanges)
140138

141139
def biosphere(self, exchanges_class=None):
142140
if exchanges_class is not None:
143-
warnings.warn(
144-
"`exchanges_class` argument ignored; must be `ReadOnlyExchanges`"
145-
)
141+
warnings.warn("`exchanges_class` argument ignored; must be `ReadOnlyExchanges`")
146142
return super().biosphere(exchanges_class=ReadOnlyExchanges)
147143

148144
def production(self, include_substitution=False, exchanges_class=None):
149145
if exchanges_class is not None:
150-
warnings.warn(
151-
"`exchanges_class` argument ignored; must be `ReadOnlyExchanges`"
152-
)
146+
warnings.warn("`exchanges_class` argument ignored; must be `ReadOnlyExchanges`")
153147
return super().production(
154148
include_substitution=include_substitution, exchanges_class=ReadOnlyExchanges
155149
)
156150

157151
def substitution(self, exchanges_class=None):
158152
if exchanges_class is not None:
159-
warnings.warn(
160-
"`exchanges_class` argument ignored; must be `ReadOnlyExchanges`"
161-
)
153+
warnings.warn("`exchanges_class` argument ignored; must be `ReadOnlyExchanges`")
162154
return super().substitution(exchanges_class=ReadOnlyExchanges)
163155

164-
def upstream(
165-
self, kinds=labels.technosphere_negative_edge_types, exchanges_class=None
166-
):
156+
def upstream(self, kinds=labels.technosphere_negative_edge_types, exchanges_class=None):
167157
if exchanges_class is not None:
168-
warnings.warn(
169-
"`exchanges_class` argument ignored; must be `ReadOnlyExchanges`"
170-
)
158+
warnings.warn("`exchanges_class` argument ignored; must be `ReadOnlyExchanges`")
171159
return super().upstream(kinds=kinds, exchanges_class=ReadOnlyExchanges)

multifunctional/node_dispatch.py

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,7 @@
33
from bw2data.backends.proxies import Activity
44
from bw2data.backends.schema import ActivityDataset
55

6-
from .node_classes import (
7-
MaybeMultifunctionalProcess,
8-
ReadOnlyProcessWithReferenceProduct,
9-
)
6+
from .node_classes import MaybeMultifunctionalProcess, ReadOnlyProcessWithReferenceProduct
107

118

129
def multifunctional_node_dispatcher(node_obj: Optional[ActivityDataset] = None) -> Activity:

multifunctional/supplemental.py

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,7 @@
44
def add_product_node_properties_to_exchange(obj: dict) -> dict:
55
"""Add properties from products to the exchange to make them available during allocation."""
66
this = (obj["database"], obj["code"])
7-
for exc in filter(
8-
lambda x: x.get("functional") and "input" in x, obj.get("exchanges", [])
9-
):
7+
for exc in filter(lambda x: x.get("functional") and "input" in x, obj.get("exchanges", [])):
108
if exc.get("type") == "production":
119
# Keep as separate because it should eventually be an output, not an input...
1210
other = exc["input"]

tests/conftest.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,12 @@
33
import pytest
44
from bw2data.tests import bw2test
55
from fixtures.basic import DATA as BASIC_DATA
6+
from fixtures.errors import DATA as ERRORS_DATA
67
from fixtures.internal_linking import DATA as INTERNAL_LINKING_DATA
78
from fixtures.product_properties import DATA as PP_DATA
89
from fixtures.products import DATA as PRODUCT_DATA
9-
from fixtures.errors import DATA as ERRORS_DATA
1010

11-
from multifunctional import allocation_before_writing, MultifunctionalDatabase
11+
from multifunctional import MultifunctionalDatabase, allocation_before_writing
1212

1313

1414
@pytest.fixture

tests/test_allocation_before_write.py

Lines changed: 3 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -108,9 +108,7 @@ def check_basic_allocation_results(factor_1, factor_2, database):
108108

109109

110110
def test_without_allocation(allocate_then_write):
111-
nodes = sorted(
112-
allocate_then_write, key=lambda x: (x["name"], x.get("reference product", ""))
113-
)
111+
nodes = sorted(allocate_then_write, key=lambda x: (x["name"], x.get("reference product", "")))
114112
assert len(nodes) == 4
115113

116114
assert isinstance(nodes[0], mf.MaybeMultifunctionalProcess)
@@ -132,9 +130,7 @@ def test_without_allocation(allocate_then_write):
132130
def test_price_allocation_strategy_label(allocate_then_write):
133131
allocate_then_write.metadata["default_allocation"] = "price"
134132
bd.get_node(code="1").allocate()
135-
nodes = sorted(
136-
allocate_then_write, key=lambda x: (x["name"], x.get("reference product", ""))
137-
)
133+
nodes = sorted(allocate_then_write, key=lambda x: (x["name"], x.get("reference product", "")))
138134

139135
assert not nodes[0].get("mf_strategy_label")
140136
assert nodes[1].get("mf_strategy_label") == "property allocation by 'price'"
@@ -177,9 +173,7 @@ def test_allocation_uses_existing(allocate_then_write):
177173
def test_allocation_already_allocated(allocate_then_write):
178174
allocate_then_write.metadata["default_allocation"] = "price"
179175
bd.get_node(code="1").allocate()
180-
node = sorted(
181-
allocate_then_write, key=lambda x: (x["name"], x.get("reference product", ""))
182-
)[2]
176+
node = sorted(allocate_then_write, key=lambda x: (x["name"], x.get("reference product", "")))[2]
183177

184178
assert mf.generic_allocation(node, None) == []
185179

tests/test_allocation_with_product_properties.py

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,7 @@
88

99

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

1513
assert isinstance(nodes[0], MaybeMultifunctionalProcess)
1614
assert nodes[0]["name"] == "first product"
@@ -170,9 +168,7 @@ def test_allocation_uses_existing(product_properties):
170168
def test_allocation_already_allocated(product_properties):
171169
product_properties.metadata["default_allocation"] = "price"
172170
bd.get_node(code="1").allocate()
173-
node = sorted(
174-
product_properties, key=lambda x: (x["name"], x.get("reference product", ""))
175-
)[3]
171+
node = sorted(product_properties, key=lambda x: (x["name"], x.get("reference product", "")))[3]
176172

177173
assert generic_allocation(node, None) == []
178174

tests/test_allocation_with_products.py

Lines changed: 3 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,7 @@
88

99

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

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

108106

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

114110
assert len(nodes) == 3
115111

@@ -167,9 +163,7 @@ def test_allocation_uses_existing(products):
167163
def test_allocation_already_allocated(products):
168164
products.metadata["default_allocation"] = "price"
169165
bd.get_node(code="1").allocate()
170-
node = sorted(products, key=lambda x: (x["name"], x.get("reference product", "")))[
171-
3
172-
]
166+
node = sorted(products, key=lambda x: (x["name"], x.get("reference product", "")))[3]
173167

174168
assert generic_allocation(node, None) == []
175169

0 commit comments

Comments
 (0)