docs: def relocate_model(part, target_parent, name=None, include_children=True):
      """
      Move the `Part` model to target parent.
  
      .. versionadded:: 2.3
  
      :param part: `Part` object to be moved
      :type part: :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 model.
      :raises IllegalArgumentError: if target_parent is descendant of part
      """
      if target_parent.id in get_illegal_targets(part, include={part.id}):
          raise IllegalArgumentError('cannot relocate part "{}" under target parent "{}", because the target is part of '
                                     'its descendants'.format(part.name, target_parent.name))
  
      # First, if the user doesn't provide the name, then just use the default "Clone - ..." name
      if not name:
          name = "CLONE - {}".format(part.name)
  
      # The description cannot be added when creating a model, so edit the model after creation.
      part_desc = part._json_data['description']
      moved_part_model = target_parent.add_model(name=name, multiplicity=part.multiplicity)
      if part_desc:
          moved_part_model.edit(description=str(part_desc))
  
      # Map the current part model id with newly created part model Object
      get_mapping_dictionary().update({part.id: moved_part_model})
  
      # Loop through properties and retrieve their type, description and unit
      list_of_properties_sorted_by_order = part.properties
      list_of_properties_sorted_by_order.sort(key=lambda x: x._json_data['order'])
      for prop in list_of_properties_sorted_by_order:
          prop_type = prop._json_data.get('property_type')
          desc = prop._json_data.get('description')
          unit = prop._json_data.get('unit')
          options = prop._json_data.get('options')
  
          # On "Part references" properties, the models referenced also need to be added
          if prop_type == PropertyType.REFERENCES_VALUE:
              referenced_part_ids = [referenced_part.id for referenced_part in prop.value]
              moved_prop = moved_part_model.add_property(name=prop.name, description=desc, property_type=prop_type,
                                                         default_value=referenced_part_ids)
  
          # On "Attachment" properties, attachments needs to be downloaded and re-uploaded to the new property.
          elif prop_type == PropertyType.ATTACHMENT_VALUE:
              moved_prop = moved_part_model.add_property(name=prop.name, description=desc, property_type=prop_type)
              if prop.value:
                  attachment_name = prop._json_data['value'].split('/')[-1]
                  with temp_chdir() as target_dir:
                      full_path = os.path.join(target_dir or os.getcwd(), attachment_name)
                      prop.save_as(filename=full_path)
                      moved_prop.upload(full_path)
  
          # Other properties are quite straightforward
          else:
              moved_prop = moved_part_model.add_property(name=prop.name, description=desc, property_type=prop_type,
                                                         default_value=prop.value, unit=unit, options=options)
  
          # Map the current property model id with newly created property model Object
          get_mapping_dictionary()[prop.id] = moved_prop
  
      # Now copy the sub-tree of the part
      if include_children:
          # Populate the part so multiple children retrieval is not needed
          part.populate_descendants()
          # For each part, recursively run this function
          for sub_part in part._cached_children:
              relocate_model(part=sub_part, target_parent=moved_part_model, name=sub_part.name,
                             include_children=include_children)
      return moved_part_model