Source code for bidict._delegating_mixins

# -*- coding: utf-8 -*-
# Copyright 2009-2019 Joshua Bronson. All Rights Reserved.
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at

#                    * Welcome to the bidict source code *

# Doing a code review? You'll find a "Code review nav" comment like the one
# below at the top and bottom of the most important source files. This provides
# a suggested initial path through the source when reviewing.
# Note: If you aren't reading this on, you may be
# viewing an outdated version of the code. Please head to GitHub to review the
# latest version, which contains important improvements over older versions.
# Thank you for reading and for any feedback you provide.

#                             * Code review nav *
# ← Prev:    Current:   Next: →

r"""Provides mixin classes that delegate to ``self._fwdm`` for various operations.

This allows methods such as :meth:`bidict.bidict.items`
to be implemented in terms of a ``self._fwdm.items()`` call,
which is potentially much more efficient (e.g. in CPython 2)
compared to the implementation inherited from :class:``
(which returns ``[(key, self[key]) for key in self]`` in Python 2).

Because this depends on implementation details that aren't necessarily true
(such as the bidict's values being the same as its ``self._fwdm.values()``,
which is not true for e.g. ordered bidicts where ``_fwdm``\'s values are nodes),
these should always be mixed in at a layer below a more general layer,
as they are in e.g. :class:`~bidict.frozenbidict`
which extends :class:`~bidict.BidictBase`.

See the :ref:`extending:Sorted Bidict Recipes`
for another example of where this comes into play.
``SortedBidict`` extends :class:`bidict.MutableBidict`
rather than :class:`bidict.bidict`
to avoid inheriting these mixins,
which are incompatible with the backing

from .compat import PY2

_KEYS_METHODS = ('keys',) + (('viewkeys', 'iterkeys') if PY2 else ())
_ITEMS_METHODS = ('items',) + (('viewitems', 'iteritems') if PY2 else ())
    'keys': 'A set-like object providing a view on the contained keys.',
    'items': 'A set-like object providing a view on the contained items.',
if PY2:
    _DOCSTRING_BY_METHOD['viewitems'] = _DOCSTRING_BY_METHOD['items']
    _DOCSTRING_BY_METHOD['keys'] = 'A list of the contained keys.'
    _DOCSTRING_BY_METHOD['items'] = 'A list of the contained items.'

def _make_method(methodname):
    def method(self):
        return getattr(self._fwdm, methodname)()  # pylint: disable=protected-access
    method.__name__ = methodname
    method.__doc__ = _DOCSTRING_BY_METHOD.get(methodname, '')
    return method

def _make_fwdm_delegating_mixin(clsname, methodnames):
    clsdict = dict({name: _make_method(name) for name in methodnames}, __slots__=())
    return type(clsname, (object,), clsdict)

_DelegateKeysToFwdm = _make_fwdm_delegating_mixin('_DelegateKeysToFwdm', _KEYS_METHODS)
_DelegateItemsToFwdm = _make_fwdm_delegating_mixin('_DelegateItemsToFwdm', _ITEMS_METHODS)
_DelegateKeysAndItemsToFwdm = type(
    (_DelegateKeysToFwdm, _DelegateItemsToFwdm),
    {'__slots__': ()})

#                             * Code review nav *
# ← Prev:    Current:   Next: →