Source code for bw2data.backends.utils

import copy
import warnings
from typing import Any, Optional

import numpy as np

from bw2data import config
from bw2data.backends.schema import get_id
from bw2data.configuration import labels
from bw2data.errors import InvalidExchange, UntypedExchange
from bw2data.meta import databases, methods
from bw2data.signals import SignaledDataset
from bw2data.snowflake_ids import snowflake_id_generator


[docs] def get_csv_data_dict(ds): fields = {"name", "reference product", "unit", "location"} dd = {field: ds.get(field) for field in fields} dd["id"] = get_id(ds) return dd
[docs] def convert_backend(database_name, backend): """Convert a Database to another backend. bw2data currently supports the `default` and `json` backends. Args: * `database_name` (unicode): Name of database. * `backend` (unicode): Type of database. `backend` should be recoginized by `DatabaseChooser`. Returns `False` if the old and new backend are the same. Otherwise returns an instance of the new Database object. """ if database_name not in databases: raise ValueError(f"Can't find database {database_name}") from bw2data import projects from bw2data.database import Database db = Database(database_name) if db.backend == backend: return False if backend == "iotable" and projects.dataset.is_sourced: raise ValueError("`iotable` backend not consistent with `sourced` project") # Needed to convert from async json dict data = db.load(as_dict=True) if database_name in config.cache: del config.cache[database_name] metadata = copy.deepcopy(db.metadata) metadata["backend"] = str(backend) del databases[database_name] with warnings.catch_warnings(): warnings.simplefilter("ignore") new_db = Database(database_name, backend) new_db.register(**metadata) new_db.write(data, searchable=databases[database_name].get("searchable")) return new_db
[docs] def check_exchange(exc): """Check exchange data validity when processing""" if "type" not in exc: raise UntypedExchange if "amount" not in exc or "input" not in exc: raise InvalidExchange if np.isnan(exc["amount"]) or np.isinf(exc["amount"]): raise ValueError("Invalid amount in exchange {}".format(exc))
[docs] def dict_as_activitydataset(ds: Any, add_snowflake_id: bool = False) -> dict: val = { "data": ds, "database": ds["database"], "code": ds["code"], "location": ds.get("location"), "name": ds.get("name"), "product": ds.get("reference product"), "type": ds.get("type", labels.process_node_default), } # Use during `insert_many` calls as these skip auto id generation because they don't call # `.save()` if add_snowflake_id: val["id"] = next(snowflake_id_generator) return val
[docs] def dict_as_exchangedataset(ds: Any) -> dict: return { "data": ds, "input_database": ds["input"][0], "input_code": ds["input"][1], "output_database": ds["output"][0], "output_code": ds["output"][1], "type": ds["type"], }
[docs] def get_obj_as_dict(cls: SignaledDataset, obj_id: Optional[int]) -> dict: """ Loads an object's data from the database as a dictionary. The format used is that of the serialization of revisions (see also the `dict_as_*` functions above); in particular, an empty dictionary is returned if the ID is `None` (but not if the object does not exist). """ if obj_id is None: return {} to_dict = globals()["dict_as_" + cls.__name__.lower()] obj = cls.get_by_id(obj_id) ret = to_dict(obj.data) ret["id"] = obj_id return ret
[docs] def replace_cfs(old_key, new_key): """Replace ``old_key`` with ``new_key`` in characterization factors. Returns list of modified methods.""" from bw2data.method import Method altered_methods = [] for name in methods: changed = False data = Method(name).load() for line in data: if line[0] == old_key: line[0], changed = new_key, True if changed: Method(name).write(data) altered_methods.append(name) return altered_methods
[docs] def retupleize_geo_strings(value): """Transform data from SQLite representation to Python objects. We are using a SQLite3 cursor, which means that the Peewee data conversion code is not called. So ``('foo', 'bar')`` is stored as a string, not a tuple. This code tries to do this conversion correctly. TODO: Adapt what Peewee does in this case?""" if not value: return value elif "(" not in value: return value try: # Is this a dirty, dirty hack, or inspiration? # Location is retrieved as a string from the database # The alternative is to retrieve and process the # entire activity dataset... return eval(value) except NameError: # Not everything with a parentheses is a tuple. return value