[utils] Allow duration strings in filter

Closes #1309
This commit is contained in:
pukkandan 2021-10-17 01:04:00 +05:30
parent ec3f6640c1
commit 18f96d129b
No known key found for this signature in database
GPG key ID: 0F00D95A001F4698
2 changed files with 21 additions and 26 deletions

View file

@ -1231,6 +1231,7 @@ def test_match_str(self):
self.assertFalse(match_str('x>2K', {'x': 1200})) self.assertFalse(match_str('x>2K', {'x': 1200}))
self.assertTrue(match_str('x>=1200 & x < 1300', {'x': 1200})) self.assertTrue(match_str('x>=1200 & x < 1300', {'x': 1200}))
self.assertFalse(match_str('x>=1100 & x < 1200', {'x': 1200})) self.assertFalse(match_str('x>=1100 & x < 1200', {'x': 1200}))
self.assertTrue(match_str('x > 1:0:0', {'x': 3700}))
# String # String
self.assertFalse(match_str('y=a212', {'y': 'foobar42'})) self.assertFalse(match_str('y=a212', {'y': 'foobar42'}))

View file

@ -4756,7 +4756,6 @@ def _match_one(filter_part, dct, incomplete):
(?P<key>[a-z_]+) (?P<key>[a-z_]+)
\s*(?P<negation>!\s*)?(?P<op>%s)(?P<none_inclusive>\s*\?)?\s* \s*(?P<negation>!\s*)?(?P<op>%s)(?P<none_inclusive>\s*\?)?\s*
(?: (?:
(?P<intval>[0-9.]+(?:[kKmMgGtTpPeEzZyY]i?[Bb]?)?)|
(?P<quote>["\'])(?P<quotedstrval>.+?)(?P=quote)| (?P<quote>["\'])(?P<quotedstrval>.+?)(?P=quote)|
(?P<strval>.+?) (?P<strval>.+?)
) )
@ -4764,40 +4763,35 @@ def _match_one(filter_part, dct, incomplete):
''' % '|'.join(map(re.escape, COMPARISON_OPERATORS.keys()))) ''' % '|'.join(map(re.escape, COMPARISON_OPERATORS.keys())))
m = operator_rex.search(filter_part) m = operator_rex.search(filter_part)
if m: if m:
unnegated_op = COMPARISON_OPERATORS[m.group('op')] m = m.groupdict()
if m.group('negation'): unnegated_op = COMPARISON_OPERATORS[m['op']]
if m['negation']:
op = lambda attr, value: not unnegated_op(attr, value) op = lambda attr, value: not unnegated_op(attr, value)
else: else:
op = unnegated_op op = unnegated_op
actual_value = dct.get(m.group('key')) comparison_value = m['quotedstrval'] or m['strval'] or m['intval']
if (m.group('quotedstrval') is not None if m['quote']:
or m.group('strval') is not None comparison_value = comparison_value.replace(r'\%s' % m['quote'], m['quote'])
actual_value = dct.get(m['key'])
numeric_comparison = None
if isinstance(actual_value, compat_numeric_types):
# If the original field is a string and matching comparisonvalue is # If the original field is a string and matching comparisonvalue is
# a number we should respect the origin of the original field # a number we should respect the origin of the original field
# and process comparison value as a string (see # and process comparison value as a string (see
# https://github.com/ytdl-org/youtube-dl/issues/11082). # https://github.com/ytdl-org/youtube-dl/issues/11082)
or actual_value is not None and m.group('intval') is not None
and isinstance(actual_value, compat_str)):
comparison_value = m.group('quotedstrval') or m.group('strval') or m.group('intval')
quote = m.group('quote')
if quote is not None:
comparison_value = comparison_value.replace(r'\%s' % quote, quote)
else:
if m.group('op') in STRING_OPERATORS:
raise ValueError('Operator %s only supports string values!' % m.group('op'))
try: try:
comparison_value = int(m.group('intval')) numeric_comparison = int(comparison_value)
except ValueError: except ValueError:
comparison_value = parse_filesize(m.group('intval')) numeric_comparison = parse_filesize(comparison_value)
if comparison_value is None: if numeric_comparison is None:
comparison_value = parse_filesize(m.group('intval') + 'B') numeric_comparison = parse_filesize(f'{comparison_value}B')
if comparison_value is None: if numeric_comparison is None:
raise ValueError( numeric_comparison = parse_duration(comparison_value)
'Invalid integer value %r in filter part %r' % ( if numeric_comparison is not None and m['op'] in STRING_OPERATORS:
m.group('intval'), filter_part)) raise ValueError('Operator %s only supports string values!' % m['op'])
if actual_value is None: if actual_value is None:
return incomplete or m.group('none_inclusive') return incomplete or m['none_inclusive']
return op(actual_value, comparison_value) return op(actual_value, comparison_value if numeric_comparison is None else numeric_comparison)
UNARY_OPERATORS = { UNARY_OPERATORS = {
'': lambda v: (v is True) if isinstance(v, bool) else (v is not None), '': lambda v: (v is True) if isinstance(v, bool) else (v is not None),