def register(**criteria):
    """
    class decorator to add :class:`Part <cqparts.Part>` or
    :class:`Assembly <cqparts.Assembly>` to the ``cqparts`` search index:

    .. testcode::

        import cqparts
        from cqparts.params import *

        # Created Part or Assembly
        @cqparts.search.register(
            type='motor',
            current_class='dc',
            part_number='ABC123X',
        )
        class SomeMotor(cqparts.Assembly):
            shaft_diam = PositiveFloat(5)
            def make_components(self):
                return {}  # build assembly content

        motor_class = cqparts.search.find(part_number='ABC123X')
        motor = motor_class(shaft_diam=6.0)

    Then use :meth:`find` &/or :meth:`search` to instantiate it.

    .. warning::

        Multiple classes *can* be registered with identical criteria, but
        should be avoided.

        If multiple classes share the same criteria, :meth:`find` will never
        yield the part you want.

        Try adding unique criteria, such as *make*, *model*, *part number*,
        *library name*, &/or *author*.

        To avoid this, learn more in :ref:`tutorial_component-index`.
    """

    def inner(cls):
        # Add class references to search index
        class_list.add(cls)
        for (category, value) in criteria.items():
            index[category][value].add(cls)

        # Retain search criteria
        _entry = dict((k, set([v])) for (k, v) in criteria.items())
        if cls not in class_criteria:
            class_criteria[cls] = _entry
        else:
            for key in _entry.keys():
                class_criteria[cls][key] = class_criteria[cls].get(key, set()) | _entry[key]

        # Return class
        return cls

    return inner