Example #1
0
def add_relation(id,
                 relation_type,
                 target_id=None,
                 target_url=None,
                 organization=None,
                 detect=None):  # pylint: disable=redefined-builtin
    """ Add relation(s) to work item.
    """

    if target_id is None and target_url is None:
        raise CLIError('--target-id or --target-url must be provided')

    organization = resolve_instance(detect=detect, organization=organization)
    patch_document = []
    client = get_work_item_tracking_client(organization)

    relation_types_from_service = client.get_relation_types()
    relation_type_system_name = get_system_relation_name(
        relation_types_from_service, relation_type)

    patch_document = []
    if target_id is not None:
        target_work_item_ids = target_id.split(',')
        work_item_query_clause = []
        for target_work_item_id in target_work_item_ids:
            work_item_query_clause.append(
                '[System.Id] = {}'.format(target_work_item_id))

        wiql_query_format = 'SELECT [System.Id] FROM WorkItems WHERE ({})'
        wiql_query_to_get_target_work_items = wiql_query_format.format(
            ' OR '.join(work_item_query_clause))

        wiql_object = Wiql()
        wiql_object.query = wiql_query_to_get_target_work_items
        target_work_items = client.query_by_wiql(wiql=wiql_object).work_items

        if len(target_work_items) != len(target_work_item_ids):
            raise CLIError('Id(s) supplied in --target-id is not valid')

        for target_work_item in target_work_items:
            op = _create_patch_operation('add', '/relations/-',
                                         relation_type_system_name,
                                         target_work_item.url)
            patch_document.append(op)

    if target_url is not None:
        target_urls = target_url.split(',')

        for url in target_urls:
            op = _create_patch_operation('add', '/relations/-',
                                         relation_type_system_name, url)
            patch_document.append(op)

    client.update_work_item(document=patch_document, id=id)
    work_item = client.get_work_item(id, expand='All')
    work_item = fill_friendly_name_for_relations_in_work_item(
        relation_types_from_service, work_item)

    return work_item
Example #2
0
def query_work_items(wiql=None, id=None, path=None, organization=None, project=None, detect=None):  # pylint: disable=redefined-builtin
    """Query for a list of work items. Only supports flat queries.
    :param wiql: The query in Work Item Query Language format.  Ignored if --id or --path is specified.
    :type wiql: str
    :param id: The ID of an existing query.  Required unless --path or --wiql are specified.
    :type id: str
    :param path: The path of an existing query.  Ignored if --id is specified.
    :type path: str
    :rtype: :class:`<WorkItem> <v5_0.work-item-tracking.models.WorkItem>`
    """
    if wiql is None and path is None and id is None:
        raise CLIError("Either the --wiql, --id, or --path argument must be specified.")
    organization, project = resolve_instance_and_project(
        detect=detect, organization=organization, project=project, project_required=False)
    client = get_work_item_tracking_client(organization)
    if id is None and path is not None:
        if project is None:
            raise CLIError("The --project argument must be specified for this query.")
        query = client.get_query(project=project, query=path)
        id = query.id
    if id is not None:
        query_result = client.query_by_id(id=id)
    else:
        wiql_object = Wiql()
        wiql_object.query = wiql
        query_result = client.query_by_wiql(wiql=wiql_object)
    if query_result.work_items:
        _last_query_result[_LAST_QUERY_RESULT_KEY] = query_result  # store query result for table view
        safety_buffer = 100  # a buffer in the max url length to protect going over the limit
        remaining_url_length = 2048 - safety_buffer
        remaining_url_length -= len(organization)
        # following subtracts relative url, the asof parameter and beginning of id and field parameters.
        # asof value length will vary, but this should be the longest possible
        remaining_url_length -=\
            len('/_apis/wit/workItems?ids=&fields=&asOf=2017-11-07T17%3A05%3A34.06699999999999999Z')
        fields = []
        fields_length_in_url = 0
        if query_result.columns:
            for field_ref in query_result.columns:
                fields.append(field_ref.reference_name)
                if fields_length_in_url > 0:
                    fields_length_in_url += 3  # add 3 for %2C delimiter
                fields_length_in_url += len(uri_quote(field_ref.reference_name))
                if fields_length_in_url > 800:
                    logger.info("Not retrieving all fields due to max url length.")
                    break
        remaining_url_length -= fields_length_in_url
        max_work_items = 1000
        work_items_batch_size = 200
        current_batch = []
        work_items = []
        work_item_url_length = 0
        for work_item_ref in query_result.work_items:
            if len(work_items) >= max_work_items:
                logger.info("Only retrieving the first %s work items.", max_work_items)
                break
            if work_item_url_length > 0:
                work_item_url_length += 3  # add 3 for %2C delimiter
            work_item_url_length += len(str(work_item_ref.id))
            current_batch.append(work_item_ref.id)

            if remaining_url_length - work_item_url_length <= 0 or len(current_batch) == work_items_batch_size:
                # url is near max length, go ahead and send first request for details.
                # url can go over by an id length because we have a safety buffer
                current_batched_items = client.get_work_items(ids=current_batch,
                                                              as_of=query_result.as_of,
                                                              fields=fields)
                for work_item in current_batched_items:
                    work_items.append(work_item)
                current_batch = []
                work_item_url_length = 0

        if current_batch:
            current_batched_items = client.get_work_items(ids=current_batch,
                                                          as_of=query_result.as_of,
                                                          fields=fields)
            for work_item in current_batched_items:
                work_items.append(work_item)
        # put items in the same order they appeared in the initial query results
        work_items = sorted(work_items, key=_get_sort_key_from_last_query_results)
        return work_items
    return None