Source code for schrodinger.application.matsci.qexsd.qespresso.utils.mapping
#
# Copyright (c), 2015-2016, Quantum Espresso Foundation and SISSA (Scuola
# Internazionale Superiore di Studi Avanzati). All rights reserved.
# This file is distributed under the terms of the MIT License. See the
# file 'LICENSE' in the root directory of the present distribution, or
# http://opensource.org/licenses/MIT.
# Authors: Davide Brunato
#
"""
Useful classes for building mapping structures.
"""
from collections import MutableMapping
[docs]class BiunivocalMap(MutableMapping):
"""
A dictionary that implements a bijective correspondence, namely with constraints
of uniqueness both on keys that on values.
"""
[docs] def __init__(self, *args, **kwargs):
self.__map = {}
self.__inverse = {}
self.update(*args, **kwargs)
def __getitem__(self, key):
if key in self.__map:
return self.__map[key]
if hasattr(self.__class__, '__missing__'):
return getattr(self.__class__, '__missing__')(self, key)
raise KeyError(key)
def __setitem__(self, key, item):
try:
if self.__inverse[item] != key:
raise ValueError(
"Value '{0}' is already mapped by another key!".format(
item))
except KeyError:
if key in self.__map:
del self.__inverse[self.__map[key]]
self.__map[key] = item
self.__inverse[item] = key
else:
del self.__inverse[self.__map[key]]
self.__map[key] = item
self.__inverse[item] = key
def __delitem__(self, key):
del self.__inverse[self.__map[key]]
del self.__map[key]
def __iter__(self):
return iter(self.__map)
[docs] def __len__(self):
return len(self.__map)
[docs] def __contains__(self, key):
return key in self.__map
def __repr__(self):
return repr(self.__map)
[docs] def copy(self):
if self.__class__ is BiunivocalMap:
return BiunivocalMap(self.__map.copy())
import copy
__map = self.__map
try:
self.__map = {}
c = copy.copy(self)
finally:
self.__map = __map
c.update(self)
return c
[docs] @classmethod
def fromkeys(cls, iterable, value=None):
d = cls()
for key in iterable:
d[key] = value
return d
[docs] def getkey(self, value, default=None):
"""
If value is in dictionary's values, return the key correspondent
to the value, else return None.
:param value: Value to map
:param default: Default to return if the value is not in the map values
"""
try:
return self.__inverse[value]
except KeyError:
return default
[docs] def inverse(self):
"""Return a copy of the inverse dictionary."""
return self.__inverse.copy()