bw-functional 0b95__tar.gz → 0b97__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (24) hide show
  1. {bw_functional-0b95/bw_functional.egg-info → bw_functional-0b97}/PKG-INFO +3 -1
  2. {bw_functional-0b95 → bw_functional-0b97}/bw_functional/__init__.py +3 -7
  3. {bw_functional-0b95 → bw_functional-0b97}/bw_functional/allocation.py +4 -6
  4. {bw_functional-0b95 → bw_functional-0b97}/bw_functional/convert.py +4 -8
  5. {bw_functional-0b95 → bw_functional-0b97}/bw_functional/database.py +4 -6
  6. {bw_functional-0b95 → bw_functional-0b97}/bw_functional/edge_classes.py +13 -9
  7. {bw_functional-0b95 → bw_functional-0b97}/bw_functional/node_classes.py +11 -13
  8. {bw_functional-0b95 → bw_functional-0b97/bw_functional.egg-info}/PKG-INFO +3 -1
  9. {bw_functional-0b95 → bw_functional-0b97}/bw_functional.egg-info/requires.txt +2 -0
  10. {bw_functional-0b95 → bw_functional-0b97}/pyproject.toml +2 -0
  11. {bw_functional-0b95 → bw_functional-0b97}/LICENSE +0 -0
  12. {bw_functional-0b95 → bw_functional-0b97}/MANIFEST.in +0 -0
  13. {bw_functional-0b95 → bw_functional-0b97}/README.md +0 -0
  14. {bw_functional-0b95 → bw_functional-0b97}/bw_functional/update.py +0 -0
  15. {bw_functional-0b95 → bw_functional-0b97}/bw_functional.egg-info/SOURCES.txt +0 -0
  16. {bw_functional-0b95 → bw_functional-0b97}/bw_functional.egg-info/dependency_links.txt +0 -0
  17. {bw_functional-0b95 → bw_functional-0b97}/bw_functional.egg-info/top_level.txt +0 -0
  18. {bw_functional-0b95 → bw_functional-0b97}/setup.cfg +0 -0
  19. {bw_functional-0b95 → bw_functional-0b97}/setup.py +0 -0
  20. {bw_functional-0b95 → bw_functional-0b97}/tests/test_allocation.py +0 -0
  21. {bw_functional-0b95 → bw_functional-0b97}/tests/test_database.py +0 -0
  22. {bw_functional-0b95 → bw_functional-0b97}/tests/test_mf_node.py +0 -0
  23. {bw_functional-0b95 → bw_functional-0b97}/tests/test_process_node.py +0 -0
  24. {bw_functional-0b95 → bw_functional-0b97}/tests/test_product_node.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: bw-functional
3
- Version: 0b95
3
+ Version: 0b97
4
4
  Summary: Code for handling multifunctional activities in Brightway
5
5
  Author-email: Chris Mutel <cmutel@gmail.com>, Marin Visscher <m.r.visscher@cml.leidenuniv.nl>
6
6
  Maintainer-email: Marin Visscher <m.r.visscher@cml.leidenuniv.nl>
@@ -23,6 +23,8 @@ Requires-Dist: blinker
23
23
  Requires-Dist: bw2data>=4.0.1
24
24
  Requires-Dist: bw2io>=0.9.1
25
25
  Requires-Dist: bw_processing>=0.9.6
26
+ Requires-Dist: loguru
27
+ Requires-Dist: pandas
26
28
  Provides-Extra: testing
27
29
  Requires-Dist: bw-functional; extra == "testing"
28
30
  Requires-Dist: bw2calc>=2.0.1; extra == "testing"
@@ -12,9 +12,7 @@ __all__ = (
12
12
  "update",
13
13
  )
14
14
 
15
- from importlib import metadata
16
- # import os
17
- from logging import getLogger
15
+ from loguru import logger
18
16
 
19
17
  from bw2data import labels
20
18
  from bw2data.subclass_mapping import DATABASE_BACKEND_MAPPING, NODE_PROCESS_CLASS_MAPPING
@@ -26,8 +24,6 @@ from .edge_classes import MFExchange, MFExchanges
26
24
  from .convert import convert_sqlite_to_functional_sqlite, convert_functional_sqlite_to_sqlite
27
25
  from .update import update, latest
28
26
 
29
- log = getLogger(__name__)
30
-
31
27
  DATABASE_BACKEND_MAPPING["functional_sqlite"] = FunctionalSQLiteDatabase
32
28
  NODE_PROCESS_CLASS_MAPPING["functional_sqlite"] = FunctionalSQLiteDatabase.node_class
33
29
 
@@ -63,7 +59,7 @@ def _check_parameterized_exchange_for_allocation(_, name):
63
59
  for key in process_keys:
64
60
  process = bd.get_activity(key)
65
61
  if not isinstance(process, Process):
66
- log.warning(f"Process {key} is not an instance of Process, skipping allocation check.")
62
+ logger.warning(f"Process {key} is not an instance of Process, skipping allocation check.")
67
63
  continue
68
64
  process.allocate()
69
65
 
@@ -75,7 +71,7 @@ def _check_and_update(dataset):
75
71
  current = dataset.data.get("bw_functional_version")
76
72
 
77
73
  if current != latest:
78
- log.info(f"Updating {dataset.name} to latest bw_functional datastructure version {latest}")
74
+ logger.info(f"Updating {dataset.name} to latest bw_functional datastructure version {latest}")
79
75
  dataset.data["bw_functional_version"] = update(current)
80
76
  dataset.save()
81
77
 
@@ -1,11 +1,9 @@
1
1
  from functools import partial
2
- from typing import Callable, List
3
- from logging import getLogger
2
+ from typing import Callable
3
+ from loguru import logger
4
4
 
5
5
  from .node_classes import Process, Product
6
6
 
7
- log = getLogger(__name__)
8
-
9
7
 
10
8
  def generic_allocation(
11
9
  process: Process,
@@ -49,7 +47,7 @@ def generic_allocation(
49
47
  products.append(product)
50
48
 
51
49
  if not products:
52
- log.warning(f"No products to allocate in process {process}")
50
+ logger.warning(f"No products to allocate in process {process}")
53
51
  return
54
52
 
55
53
  # Calculate the total value for allocation
@@ -110,7 +108,7 @@ def get_property_value(
110
108
  raise KeyError(f"Product {product} from {product.processor} missing property {property_label}")
111
109
 
112
110
  if isinstance(prop, float):
113
- log.warning("Property using legacy float format")
111
+ logger.warning("Property using legacy float format")
114
112
  return prop
115
113
 
116
114
  if prop.get("normalize", False):
@@ -1,13 +1,9 @@
1
1
  import tqdm
2
- from logging import getLogger
3
-
2
+ from loguru import logger
4
3
  import bw2data as bd
5
- from bw2data.backends import SQLiteBackend
6
4
 
7
5
  from .database import FunctionalSQLiteDatabase
8
6
 
9
- log = getLogger(__name__)
10
-
11
7
 
12
8
  def convert_sqlite_to_functional_sqlite(database_dict: dict) -> dict:
13
9
  return SQLiteToFunctionalSQLite.convert(database_dict)
@@ -145,15 +141,15 @@ class FunctionalSQLiteToSQLite:
145
141
  continue
146
142
 
147
143
  if exc["type"] != "production" and ds.get("allocation_factor"):
148
- log.info(f"Allocating exchange from {exc['input']} to {ds['name']} "
144
+ logger.info(f"Allocating exchange from {exc['input']} to {ds['name']} "
149
145
  f"with factor {ds['allocation_factor']}")
150
146
  exc["amount"] = exc["amount"] * ds['allocation_factor']
151
147
  if exc.get("formula"):
152
- log.info(f"Allocating formula from {exc['input']} to {ds['name']}: "
148
+ logger.info(f"Allocating formula from {exc['input']} to {ds['name']}: "
153
149
  f"{exc['formula']} * {ds['allocation_factor']}")
154
150
  exc["formula"] = f"{exc['formula']} * {ds['allocation_factor']}"
155
151
  if exc.get("uncertainty type"):
156
- log.warning(f"Exchange from {exc['input']} to {ds['name']} has an uncertainty distribution that "
152
+ logger.warning(f"Exchange from {exc['input']} to {ds['name']} has an uncertainty distribution that "
157
153
  f"will not be allocated")
158
154
 
159
155
  ds["exchanges"].append(exc)
@@ -1,13 +1,13 @@
1
1
  import sqlite3
2
2
  import pickle
3
3
  import datetime
4
- from logging import getLogger
5
4
  from time import time
6
5
 
7
- import numpy as np
8
- import pandas as pd
6
+ from loguru import logger
9
7
  from fsspec.implementations.zip import ZipFileSystem
10
8
 
9
+ import numpy as np
10
+ import pandas as pd
11
11
  import stats_arrays as sa
12
12
 
13
13
  from bw_processing import clean_datapackage_name, create_datapackage
@@ -17,8 +17,6 @@ from pandas._libs.missing import NAType
17
17
 
18
18
  from .node_classes import Process, Product
19
19
 
20
- log = getLogger(__name__)
21
-
22
20
  UNCERTAINTY_FIELDS = ["uncertainty_type", "loc", "scale", "shape", "minimum", "maximum"]
23
21
 
24
22
 
@@ -238,7 +236,7 @@ class FunctionalSQLiteDatabase(SQLiteBackend):
238
236
  # Close the SQLite connection
239
237
  con.close()
240
238
 
241
- log.debug(f"Processing: built tables from SQL in {time() - t:.2f} seconds")
239
+ logger.debug(f"Processing: built tables from SQL in {time() - t:.2f} seconds")
242
240
 
243
241
  return node_df, exc_df, dependents
244
242
 
@@ -1,11 +1,9 @@
1
- from logging import getLogger
1
+ from loguru import logger
2
2
  from copy import deepcopy
3
3
 
4
- from bw2data import projects, databases
4
+ from bw2data import projects, databases, errors
5
5
  from bw2data.backends.proxies import Exchange, Exchanges, ExchangeDataset
6
6
 
7
- log = getLogger(__name__)
8
-
9
7
 
10
8
  class MFExchanges(Exchanges):
11
9
  """
@@ -106,7 +104,7 @@ class MFExchange(Exchange):
106
104
  NotImplementedError: If parameterization is attempted for production exchanges.
107
105
  """
108
106
  from .node_classes import Process, Product
109
- log.debug(f"Saving {self['type']} Exchange: {self}")
107
+ logger.debug(f"Saving {self['type']} Exchange: {self}")
110
108
 
111
109
  created = self.id is None # the exchange is new if it has no id
112
110
  old = ExchangeDataset.get_by_id(self.id) if not created else None
@@ -145,12 +143,18 @@ class MFExchange(Exchange):
145
143
  signal (bool, optional): Whether to send a signal after deletion. Defaults to True.
146
144
  """
147
145
  from .node_classes import Product, Process, MFActivity
148
- log.debug(f"Deleting {self['type']} Exchange: {self}")
149
146
 
150
- super().delete(signal)
147
+ try:
148
+ function = self.input
149
+ process = self.output
150
+ except errors.UnknownObject:
151
+ logger.warning(f"Could not retrieve input or output for exchange deletion. {self['input']=}, {self['output']=}")
152
+ super().delete(signal)
153
+ return
151
154
 
152
- function = self.input
153
- process = self.output
155
+ logger.debug(f"Deleting {self['type']} Exchange: {self}")
156
+
157
+ super().delete(signal)
154
158
 
155
159
  if not isinstance(process, Process) or not isinstance(function, Product):
156
160
  return
@@ -1,15 +1,13 @@
1
- from typing import Optional, Union
2
- from logging import getLogger
1
+ from typing import Optional
2
+
3
+ from loguru import logger
3
4
 
4
5
  from bw2data import databases, get_node, labels
5
- from bw2data.backends import ExchangeDataset
6
6
  from bw2data.errors import UnknownObject, ValidityError
7
7
  from bw2data.backends.proxies import Activity, ActivityDataset
8
8
 
9
9
  from .edge_classes import MFExchanges, MFExchange
10
10
 
11
- log = getLogger(__name__)
12
-
13
11
 
14
12
  INHERITED_FIELDS = [
15
13
  "database",
@@ -41,7 +39,7 @@ class MFActivity(Activity):
41
39
  data_already_set (bool, optional): Whether the data is already set. Defaults to False.
42
40
  force_insert (bool, optional): Whether to force an insert operation. Defaults to False.
43
41
  """
44
- log.debug(f"Saving {self.__class__.__name__}: {self}")
42
+ logger.debug(f"Saving {self.__class__.__name__}: {self}")
45
43
  super().save(signal, data_already_set, force_insert)
46
44
 
47
45
  def delete(self, signal: bool = True):
@@ -53,7 +51,7 @@ class MFActivity(Activity):
53
51
  Args:
54
52
  signal (bool, optional): Whether to send a signal after deletion. Defaults to True.
55
53
  """
56
- log.debug(f"Deleting {self.__class__.__name__}: {self}")
54
+ logger.debug(f"Deleting {self.__class__.__name__}: {self}")
57
55
  super().delete(signal)
58
56
 
59
57
  @property
@@ -206,7 +204,7 @@ class Process(MFActivity):
206
204
  self.allocate()
207
205
 
208
206
  if changed_fields := [field for field in INHERITED_FIELDS if self.get(field) != old.data.get(field)]:
209
- log.info(f"Updating inherited fields {changed_fields} for products of process {self}")
207
+ logger.info(f"Updating inherited fields {changed_fields} for products of process {self}")
210
208
  for product in self.products():
211
209
  for field in changed_fields:
212
210
  product._set_inherited(field, self.get(field))
@@ -305,7 +303,7 @@ class Process(MFActivity):
305
303
  normalize = set(prop.get("normalize", True) for prop in properties)
306
304
 
307
305
  if len(units) > 1 or len(normalize) > 1:
308
- log.warning(f"Property {name} has inconsistent units or normalization across products.")
306
+ logger.warning(f"Property {name} has inconsistent units or normalization across products.")
309
307
 
310
308
  return {
311
309
  "unit": units.pop() if units else "unitless",
@@ -360,7 +358,7 @@ class Process(MFActivity):
360
358
  ValueError: If no allocation strategy is found.
361
359
  """
362
360
  if self.get("skip_allocation"):
363
- log.debug(f"Skipping allocation for {repr(self)} (id: {self.id})")
361
+ logger.debug(f"Skipping allocation for {repr(self)} (id: {self.id})")
364
362
  return
365
363
 
366
364
  from . import allocation_strategies, property_allocation
@@ -376,7 +374,7 @@ class Process(MFActivity):
376
374
  "Can't find `default_allocation` in input arguments, or process/database metadata."
377
375
  )
378
376
 
379
- log.debug(f"Allocating {repr(self)} (id: {self.id}) with strategy {strategy_label}")
377
+ logger.debug(f"Allocating {repr(self)} (id: {self.id}) with strategy {strategy_label}")
380
378
 
381
379
  alloc_function = allocation_strategies.get(strategy_label, property_allocation(strategy_label))
382
380
  alloc_function(self)
@@ -439,7 +437,7 @@ class Product(MFActivity):
439
437
 
440
438
  # Check if the `processor` is the same as the one in the production edge otherwise update it
441
439
  if not created and edge.output != self["processor"]:
442
- log.info(f"Switching processor for {self}")
440
+ logger.info(f"Switching processor for {self}")
443
441
  edge.output = self["processor"]
444
442
  edge.save()
445
443
 
@@ -500,7 +498,7 @@ class Product(MFActivity):
500
498
  excs = self.exchanges(kinds=["production"], reverse=True)
501
499
 
502
500
  if len(excs) > 1:
503
- log.warning(f"Multiple processing edges found for product {self['code']}.")
501
+ logger.warning(f"Multiple processing edges found for product {self['code']}.")
504
502
  return None
505
503
  if len(excs) == 0:
506
504
  return None
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: bw-functional
3
- Version: 0b95
3
+ Version: 0b97
4
4
  Summary: Code for handling multifunctional activities in Brightway
5
5
  Author-email: Chris Mutel <cmutel@gmail.com>, Marin Visscher <m.r.visscher@cml.leidenuniv.nl>
6
6
  Maintainer-email: Marin Visscher <m.r.visscher@cml.leidenuniv.nl>
@@ -23,6 +23,8 @@ Requires-Dist: blinker
23
23
  Requires-Dist: bw2data>=4.0.1
24
24
  Requires-Dist: bw2io>=0.9.1
25
25
  Requires-Dist: bw_processing>=0.9.6
26
+ Requires-Dist: loguru
27
+ Requires-Dist: pandas
26
28
  Provides-Extra: testing
27
29
  Requires-Dist: bw-functional; extra == "testing"
28
30
  Requires-Dist: bw2calc>=2.0.1; extra == "testing"
@@ -2,6 +2,8 @@ blinker
2
2
  bw2data>=4.0.1
3
3
  bw2io>=0.9.1
4
4
  bw_processing>=0.9.6
5
+ loguru
6
+ pandas
5
7
 
6
8
  [dev]
7
9
  build
@@ -33,6 +33,8 @@ dependencies = [
33
33
  "bw2data>=4.0.1",
34
34
  "bw2io>=0.9.1",
35
35
  "bw_processing>=0.9.6",
36
+ "loguru",
37
+ "pandas",
36
38
  ]
37
39
 
38
40
  [project.urls]
File without changes
File without changes
File without changes
File without changes
File without changes