# Copyright 2014 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

"""Implements a frozen dictionary-like object"""

import collections
import copy

import common.memo as memo

class frozendict(collections.Mapping):
  """A frozen dictionary class"""

  def __init__(self, *args, **kwargs):
    self._data = dict(*args, **kwargs)

  def __iter__(self):
    return iter(self._data)

  def __len__(self):
    return len(self._data)

  def __getitem__(self, key):
    return self._data[key]

  @memo.memo_i()
  def __hash__(self):
    return hash(self.itemtuple())

  def __str__(self):
    return str(self._data)

  def __repr__(self):
    return '%s(%s)' % (type(self).__name__, str(self))

  def __eq__(self, other):
    return self._data == other

  def __ne__(self, other):
    return not self == other

  def __deepcopy__(self, _memo):
    return copy.deepcopy(self._data)

  @memo.memo_i()
  def itemtuple(self):
    return tuple(sorted(self.iteritems()))

  def mutableDict(self):
    """
    Returns a mutable dictionary copy, replacing 'frozendict' with 'dict's.

    This function uses the 'copy.deepcopy' method to create a mutable deep copy
    of the dictionary.

    Note that due to the one-size-fits-all behavior of 'deepcopy', the result
    can be anything from heavyhanded to incorrect depending on the contents of
    the dictionary. The caller should make sure they understand the operation
    and its behavior on all of the dictionary's subtypes before using it.

    Returns: (dict) A mutable clone of the dictionary and its members.
    """
    return copy.deepcopy(self)

  def extend(self, **kwargs):
    """Returns a copy of this object with the 'kwargs' fields updated."""
    ndata = self.mutableDict()
    ndata.update(kwargs)
    return type(self)(**ndata)

[(27, 'common.memo.memo_i', 'memo.memo_i', True, 'import common.memo as memo\n'), (46, 'common.memo.memo_i', 'memo.memo_i', True, 'import common.memo as memo\n'), (44, 'copy.deepcopy', 'copy.deepcopy', False, 'import copy\n'), (64, 'copy.deepcopy', 'copy.deepcopy', False, 'import copy\n')]