Source code for bw2data.meta
# -*- coding: utf-8 -*-
from __future__ import print_function, unicode_literals
from eight import *
from . import config
from .project import writable_project
from .serialization import SerializedDict, PickledDict, CompoundJSONDict
from .utils import python_2_unicode_compatible
import datetime
import pprint
@python_2_unicode_compatible
[docs]
class Mapping(PickledDict):
"""A dictionary that maps object ids, like ``("Ecoinvent 2.2", 42)``, to integers. Needed because parameter arrays have integer ``row`` and ``column`` fields.
File data is saved in ``mapping.pickle``.
This dictionary does not support setting items directly; instead, use the ``add`` method to add multiple keys."""
[docs]
filename = "mapping.pickle"
@writable_project
[docs]
def add(self, keys):
"""Add a set of keys. These keys can already be in the mapping; only new keys will be added.
Args:
* *keys* (list): The keys to add.
"""
index = max(self.data.values()) if self.data else 0
for i, key in enumerate(keys):
if key not in self.data:
self.data[key] = index + i + 1
self.flush()
[docs]
def delete(self, keys):
"""Delete a set of keys.
Args:
*keys* (list): The keys to delete.
"""
for key in keys:
del self.data[key]
self.flush()
def __setitem__(self, key, value):
raise NotImplemented
def __str__(self):
return u"Mapping from databases and methods to parameter indices."
def __len__(self):
return len(self.data)
[docs]
class GeoMapping(Mapping):
"""A dictionary that maps location codes to integers. Needed because parameter arrays have integer ``geo`` fields.
File data is stored in ``geomapping.pickle``.
This dictionary does not support setting items directly; instead, use the ``add`` method to add multiple keys."""
[docs]
filename = "geomapping.pickle"
def __init__(self, *args, **kwargs):
super(GeoMapping, self).__init__(*args, **kwargs)
# At a minimum, "GLO" should always be present
if "GLO" not in self:
self.add(["GLO"])
def __str__(self):
return "Mapping from locations to parameter indices."
@python_2_unicode_compatible
[docs]
class Databases(SerializedDict):
"""A dictionary for database metadata. This class includes methods to manage database versions. File data is saved in ``databases.json``."""
[docs]
filename = "databases.json"
@writable_project
[docs]
def increment_version(self, database, number=None):
"""Increment the ``database`` version. Returns the new version."""
self.data[database]["version"] += 1
if number is not None:
self.data[database]["number"] = number
self.flush()
return self.data[database]["version"]
[docs]
def version(self, database):
"""Return the ``database`` version"""
return self.data[database].get("version")
@writable_project
[docs]
def set_modified(self, database):
self[database]['modified'] = datetime.datetime.now().isoformat()
self.flush()
@writable_project
[docs]
def set_dirty(self, database):
self.set_modified(database)
if self[database].get('dirty'):
pass
else:
self[database]['dirty'] = True
self.flush()
[docs]
def clean(self):
from . import Database
@writable_project
def _clean():
for x in self:
if self[x].get('dirty'):
Database(x).process()
del self[x]['dirty']
self.flush()
if not any(self[x].get('dirty') for x in self):
return
else:
return _clean()
@writable_project
def __delitem__(self, name):
from . import Database
try:
Database(name).delete(warn=False)
except:
pass
super(Databases, self).__delitem__(name)
@python_2_unicode_compatible
[docs]
class CalculationSetups(PickledDict):
"""A dictionary for calculation setups.
Keys:
* `inv`: List of functional units, e.g. ``[{(key): amount}, {(key): amount}]``
* `ia`: List of LCIA methods, e.g. ``[(method), (method)]``.
"""
[docs]
filename = "setups.pickle"
@python_2_unicode_compatible
[docs]
class DynamicCalculationSetups(PickledDict):
"""A dictionary for Dynamic calculation setups.
Keys:
* `inv`: List of functional units, e.g. ``[{(key): amount}, {(key): amount}]``
* `ia`: Dictionary of orst case LCIA method and the relative dynamic LCIA method, e.g. `` [{dLCIA_method_1_worstcase:dLCIA_method_1 , dLCIA_method_2_worstcase:dLCIA_method_2}]``.
"""
[docs]
filename = "dynamicsetups.pickle"
@python_2_unicode_compatible
[docs]
class Methods(CompoundJSONDict):
"""A dictionary for method metadata. File data is saved in ``methods.json``."""
[docs]
filename = "methods.json"
[docs]
class Preferences(PickledDict):
"""A dictionary of project-specific preferences."""
[docs]
filename = "preferences.pickle"
def __init__(self, *args, **kwargs):
super(Preferences, self).__init__(*args, **kwargs)
# Default preferences
if 'use_cache' not in self:
self['use_cache'] = True
[docs]
databases = Databases()
[docs]
geomapping = GeoMapping()
[docs]
normalizations = NormalizationMeta()
[docs]
preferences = Preferences()
[docs]
weightings = WeightingMeta()
[docs]
calculation_setups = CalculationSetups()
[docs]
dynamic_calculation_setups = DynamicCalculationSetups()