Exemplo n.º 1
0
def test_search_range(happi_client: Client, valve: OphydItem):
    happi_client.add_item(valve)
    # Search between two points
    res = happi_client.search_range('z', start=0, end=500)
    assert len(res) == 2
    # Search between two points, nothing found
    res = happi_client.search_range('z', start=10000, end=500000)
    assert not res
    # Search without an endpoint
    res = happi_client.search_range('z', start=0)
    assert len(res) == 2
    # Search invalid range
    with pytest.raises(ValueError):
        happi_client.search_range('z', start=1000, end=5)
Exemplo n.º 2
0
Arquivo: cli.py Projeto: pcdshub/happi
def search_parser(
    client: happi.Client,
    use_glob: bool,
    search_criteria: List[str],
) -> List[happi.SearchResult]:
    """
    Parse the user's search criteria and return the search results.

    ``search_criteria`` must be a list of key=value strings.
    If key is omitted, it will be assumed to be "name".

    Parameters
    ----------
    client : Client
        The happi client that we'll be doing searches in.
    use_glob : bool
        True if we're using glob matching, False if we're using
        regex matching.
    search_criteria : list of str
        The user's search selection from the command line.
    """
    # Get search criteria into dictionary for use by client
    client_args = {}
    range_list = []
    regex_list = []
    range_found = False

    with client.retain_cache_context():
        for user_arg in search_criteria:
            if '=' in user_arg:
                criteria, value = user_arg.split('=', 1)
            else:
                criteria = 'name'
                value = user_arg
            if criteria in client_args:
                logger.error(
                    'Received duplicate search criteria %s=%r (was %r)',
                    criteria, value, client_args[criteria])
                raise click.Abort()

            if is_a_range(value):
                start, stop = value.split(',')
                start = float(start)
                stop = float(stop)
                if start < stop:
                    new_range_list = client.search_range(criteria, start, stop)
                else:
                    logger.error('Invalid range, make sure start < stop')
                    raise click.Abort()

                if not range_found:
                    # if first range, just replace
                    range_found = True
                    range_list = new_range_list
                else:
                    # subsequent ranges, only take intersection
                    range_list = set(new_range_list) & set(range_list)

                if not range_list:
                    # we have searched via a range query.  At this point
                    # no matches, or intesection is empty. abort early
                    logger.error("No items found")
                    return []

                continue

            elif is_number(value):
                if float(value) == int(float(value)):
                    # value is an int, allow the float version (optional .0)
                    logger.debug(f'looking for int value: {value}')
                    value = f'^{int(float(value))}(\\.0+$)?$'

                    # don't translate from glob
                    client_args[criteria] = value
                    continue
                else:
                    value = str(float(value))
            else:
                logger.debug('Value %s interpreted as string', value)

            if use_glob:
                client_args[criteria] = fnmatch.translate(value)
            else:  # already using regex
                client_args[criteria] = value

        regex_list = client.search_regex(**client_args)

    # Gather final results
    final_results = []
    if regex_list and not range_list:
        # only matched with one search_regex()
        final_results = regex_list
    elif range_list and not regex_list:
        # only matched with search_range()
        final_results = range_list
    elif range_list and regex_list:
        # find the intersection between regex_list and range_list
        final_results = set(range_list) & set(regex_list)
    else:
        logger.debug('No regex or range items found')

    if not final_results:
        logger.error('No items found')
    return final_results