return tuple (label, ind) from `label_or_index`

        If `label_or_int` is a :class:`.SymbolicLabelBase` sub-instance, it
        will be stored in the `label` attribute, and the `ind` attribute will
        return the value of the label's :attr:`.FockIndex.fock_index`
        attribute.  No checks are performed for symbolic labels.

        :meth:`_check_basis_label_type` is called on `label_or_index`.

        Raises:
            ValueError: if `label_or_index` is a :class:`str` referencing an
                invalid basis state; or, if `label_or_index` is an :class:`int`
                < 0 or >= the dimension of the Hilbert space
            BasisNotSetError: if `label_or_index` is a :class:`str`, but the
                Hilbert space has no defined basis
            TypeError: if `label_or_int` is not a :class:`str`, :class:`int`,
                or :class:`.SymbolicLabelBase`, or more generally whatever
                types are allowed through the `_basis_label_types` attribute of
                the Hilbert space.

def _unpack_basis_label_or_index(self, label_or_index):
        """return tuple (label, ind) from `label_or_index`

        If `label_or_int` is a :class:`.SymbolicLabelBase` sub-instance, it
        will be stored in the `label` attribute, and the `ind` attribute will
        return the value of the label's :attr:`.FockIndex.fock_index`
        attribute.  No checks are performed for symbolic labels.

        :meth:`_check_basis_label_type` is called on `label_or_index`.

        Raises:
            ValueError: if `label_or_index` is a :class:`str` referencing an
                invalid basis state; or, if `label_or_index` is an :class:`int`
                < 0 or >= the dimension of the Hilbert space
            BasisNotSetError: if `label_or_index` is a :class:`str`, but the
                Hilbert space has no defined basis
            TypeError: if `label_or_int` is not a :class:`str`, :class:`int`,
                or :class:`.SymbolicLabelBase`, or more generally whatever
                types are allowed through the `_basis_label_types` attribute of
                the Hilbert space.
        """
        self._check_basis_label_type(label_or_index)
        if isinstance(label_or_index, str):
            label = label_or_index
            try:
                ind = self.basis_labels.index(label)
                # the above line may also raise BasisNotSetError, which we
                # don't want to catch here
            except ValueError:
                # a less confusing error message:
                raise ValueError(
                    "%r is not one of the basis labels %r"
                    % (label, self.basis_labels))
        elif isinstance(label_or_index, int):
            ind = label_or_index
            if ind < 0:
                raise ValueError("Index %d must be >= 0" % ind)
            if self.has_basis:
                if ind >= self.dimension:
                    raise ValueError(
                        "Index %s must be < the dimension %d of Hilbert "
                        "space %s" % (ind, self.dimension, self))
                label = self.basis_labels[label_or_index]
            else:
                label = str(label_or_index)
        elif isinstance(label_or_index, SymbolicLabelBase):
            label = label_or_index
            try:
                ind = label_or_index.fock_index
            except AttributeError:
                raise TypeError(
                    "label_or_index must define a fock_index attribute in "
                    "order to be used for identifying a level in a Hilbert "
                    "space")
        else:
            raise TypeError(
                "label_or_index must be an int or str, or SymbolicLabelBase, "
                "not %s" % type(label_or_index))
        return label, ind