Commit 103208e6 authored by Ophélie Gagnard's avatar Ophélie Gagnard

Downlaod: Add "<<" and ">>" operators.

"<<" and ">>" are like "<=" and ">=" except they select the
closest value and accept "Infinity" for integer comparisons.
parent a0105b6d
......@@ -477,14 +477,15 @@ class NetworkcacheClient(object):
class NetworkcacheFilter(object):
special_word_mapping = {"max":max, "min":max}
parse_criterion = re.compile("([<>]=?|==|:)").split
parse_criterion = re.compile("(<<|>>|[<>]=?|==|:)").split
operator_mapping = {
">=": operator.ge,
"<=": operator.le,
">": operator.gt,
"<": operator.lt,
"==": operator.eq,
">>": operator.ge,
"<<": operator.le,
}
def __init__(self, criterion_list=()):
......@@ -500,11 +501,10 @@ class NetworkcacheFilter(object):
raise NetworkcacheException(
'Could not parse criterion: missing or invalid separator (%s)'
% criterion)
if parsed_criterion[1] != ':':
if parsed_criterion[1] in ['<<', '>>'] and parsed_criterion[2] == "Infinity":
parsed_criterion[2] = float("inf")
else:
parsed_criterion[2] = json.loads(parsed_criterion[2])
elif parsed_criterion[2] not in self.special_word_mapping:
raise NetworkcacheException('Unknown special word %r'
% parsed_criterion[2])
parsed_criterion_list.append(parsed_criterion)
self.criterion_list = parsed_criterion_list
else:
......@@ -519,13 +519,23 @@ class NetworkcacheFilter(object):
data_dict_list = [data_dict for data_dict in data_dict_list if key in data_dict]
if not data_dict_list:
break
if op == ":":
extremum = self.special_word_mapping[value](
data_dict[key] for data_dict in data_dict_list)
data_dict_list = [data_dict for data_dict in data_dict_list
if data_dict[key] == extremum]
filtered_data_dict_list = []
if op == ">>" or op == "<<":
for data_dict in data_dict_list:
try:
if self.operator_mapping[op](data_dict[key], value):
if not filtered_data_dict_list:
filtered_data_dict_list = [data_dict]
elif data_dict[key] == filtered_data_dict_list[0][key]:
filtered_data_dict_list.append(data_dict)
elif self.operator_mapping[op](filtered_data_dict_list[0][key], data_dict[key]):
filtered_data_dict_list = [data_dict]
except TypeError:
logger.info('Comparison failed: %s %s %s'
' with types: %s %s',
data_dict[key], op, value,
type(data_dict[key]), type(value))
else:
filtered_data_dict_list = []
for data_dict in data_dict_list:
try:
if self.operator_mapping[op](data_dict[key], value):
......@@ -535,7 +545,7 @@ class NetworkcacheFilter(object):
' with types: %s %s',
data_dict[key], op, value,
type(data_dict[key]), type(value))
data_dict_list = filtered_data_dict_list
data_dict_list = filtered_data_dict_list
return data_dict_list
class NetworkcacheException(Exception):
......@@ -610,8 +620,8 @@ def cmd_upload(*args):
def cmd_download(*args):
parser = _newArgumentParser("URL of data to download.", key_help, True)
parser.add_argument('meta', nargs='*', metavar='KEY{>=,<=,==,<,>,:}VALUE',
help='Filter metadata. Each argument represents a filter with a comparison condition. The filters will be applied one by one with the arguments processed in the order of appearance.VALUE is expected to be a json dump of a comparable object in Python (strings included), except when the separator is ":" (in this case VALUE must be min or max).')
parser.add_argument('meta', nargs='*', metavar='KEY{>=,<=,==,<,>,>>,<<}VALUE',
help='Filter metadata. Each argument represents a filter with a comparison condition. The filters will be applied one by one with the arguments processed in the order of appearance. VALUE is expected to be a json dump of a comparable object in Python (strings included). "<<" and ">>" are like "<=" and ">=" except they select the closest value and accept "Infinity" for integer comparisons.')
args = parser.parse_args(args or sys.argv[1:])
nc = NetworkcacheClient(args.config)
if args.key:
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment