Move the `Part` instance to target parent and updates the properties based on the original part instance.

    .. versionadded:: 2.3

    :param part_instance: `Part` object to be moved
    :type part_instance: :class:`Part`
    :param part_model: `Part` object representing the model of part_instance
    :type part_model: :class: `Part`
    :param target_parent: `Part` object under which the desired `Part` is moved
    :type target_parent: :class:`Part`
    :param name: how the moved top-level `Part` should be called
    :type name: basestring
    :param include_children: True to move also the descendants of `Part`. If False, the children will be lost.
    :type include_children: bool
    :return: moved :class: `Part` instance

def move_part_instance(part_instance, target_parent, part_model, name=None, include_children=True):
    """
    Move the `Part` instance to target parent and updates the properties based on the original part instance.

    .. versionadded:: 2.3

    :param part_instance: `Part` object to be moved
    :type part_instance: :class:`Part`
    :param part_model: `Part` object representing the model of part_instance
    :type part_model: :class: `Part`
    :param target_parent: `Part` object under which the desired `Part` is moved
    :type target_parent: :class:`Part`
    :param name: how the moved top-level `Part` should be called
    :type name: basestring
    :param include_children: True to move also the descendants of `Part`. If False, the children will be lost.
    :type include_children: bool
    :return: moved :class: `Part` instance
    """
    # If no specific name has been required, then call in as Clone of the part_instance.
    if not name:
        name = part_instance.name

    # Retrieve the model of the future part to be created
    moved_model = get_mapping_dictionary()[part_model.id]

    # Now act based on multiplicity
    if moved_model.multiplicity == Multiplicity.ONE:
        # If multiplicity is 'Exactly 1', that means the instance was automatically created with the model, so just
        # retrieve it, map the original instance with the moved one and update the name and property values.
        moved_instance = moved_model.instances(parent_id=target_parent.id)[0]
        map_property_instances(part_instance, moved_instance)
        moved_instance = update_part_with_properties(part_instance, moved_instance, name=str(name))
    elif moved_model.multiplicity == Multiplicity.ONE_MANY:
        # If multiplicity is '1 or more', that means one instance has automatically been created with the model, so
        # retrieve it, map the original instance with the moved one and update the name and property values. Store
        # the model in a list, in case there are multiple instance those need to be recreated.
        if target_parent.id not in get_edited_one_many():
            moved_instance = moved_model.instances(parent_id=target_parent.id)[0]
            map_property_instances(part_instance, moved_instance)
            moved_instance = update_part_with_properties(part_instance, moved_instance, name=str(name))
            get_edited_one_many().append(target_parent.id)
        else:
            moved_instance = target_parent.add(name=part_instance.name, model=moved_model, suppress_kevents=True)
            map_property_instances(part_instance, moved_instance)
            moved_instance = update_part_with_properties(part_instance, moved_instance, name=str(name))
    else:
        # If multiplicity is '0 or more' or '0 or 1', it means no instance has been created automatically with the
        # model, so then everything must be created and then updated.
        moved_instance = target_parent.add(name=name, model=moved_model, suppress_kevents=True)
        map_property_instances(part_instance, moved_instance)
        moved_instance = update_part_with_properties(part_instance, moved_instance, name=str(name))

    # If include_children is True, then recursively call this function for every descendant. Keep the name of the
    # original sub-instance.
    if include_children:
        for sub_instance in part_instance._cached_children:
            move_part_instance(part_instance=sub_instance, target_parent=moved_instance,
                               part_model=sub_instance.model(),
                               name=sub_instance.name, include_children=True)

    return moved_instance