Handle Non-Alphanumerical Edge Cases When Searching Themes By Colour (#22699)
* Introduce convert_to_hex function for color queries on search for themes * make convert_to_hex use hexadecimal rather than alphanumeric, more explicit ValueError * testing * lint
This commit is contained in:
Родитель
645abccd81
Коммит
e744e269d3
|
@ -1,3 +1,4 @@
|
|||
import re
|
||||
from datetime import datetime
|
||||
|
||||
from django.utils import translation
|
||||
|
@ -433,13 +434,21 @@ class AddonPromotedQueryParam(AddonQueryMultiParam):
|
|||
class AddonColorQueryParam(AddonQueryParam):
|
||||
query_param = 'color'
|
||||
|
||||
def convert_to_hsl(self, hexvalue):
|
||||
def convert_to_hex(self, color):
|
||||
color = re.sub(r'[^0-9A-Fa-f]', '', color)[:6]
|
||||
if len(color) == 3:
|
||||
color = ''.join(2 * c for c in color)
|
||||
if len(color) != 6:
|
||||
raise ValueError
|
||||
else:
|
||||
return color
|
||||
|
||||
def convert_to_hsl(self, color):
|
||||
# The API is receiving color as a hex string. We store colors in HSL
|
||||
# as colorgram generates it (which is on a 0 to 255 scale for each
|
||||
# component), so some conversion is necessary.
|
||||
if len(hexvalue) == 3:
|
||||
hexvalue = ''.join(2 * c for c in hexvalue)
|
||||
try:
|
||||
hexvalue = self.convert_to_hex(color)
|
||||
rgb = tuple(bytearray.fromhex(hexvalue))
|
||||
except ValueError as err:
|
||||
raise ValueError(
|
||||
|
@ -449,7 +458,7 @@ class AddonColorQueryParam(AddonQueryParam):
|
|||
|
||||
def get_value(self):
|
||||
color = self.query_data.get(self.query_param, '')
|
||||
return self.convert_to_hsl(color.upper().lstrip('#')[:6]) if color else None
|
||||
return self.convert_to_hsl(color) if color else None
|
||||
|
||||
def get_es_query(self):
|
||||
# Thresholds for saturation & luminosity that dictate which query to
|
||||
|
|
|
@ -1048,6 +1048,18 @@ class TestSearchParameterFilter(FilterTestsBase):
|
|||
{'range': {'colors.ratio': {'gte': 0.25}}},
|
||||
]
|
||||
|
||||
qs = self._filter(data={'color': '00$#ff*$ff'})
|
||||
filter_ = qs['query']['bool']['filter']
|
||||
assert len(filter_) == 1
|
||||
inner = filter_[0]['nested']['query']['bool']['filter']
|
||||
assert len(inner) == 4
|
||||
assert inner == [
|
||||
{'range': {'colors.s': {'gt': 6.375}}},
|
||||
{'range': {'colors.l': {'gt': 12.75, 'lt': 249.9}}},
|
||||
{'range': {'colors.h': {'gte': 101, 'lte': 153}}},
|
||||
{'range': {'colors.ratio': {'gte': 0.25}}},
|
||||
]
|
||||
|
||||
def test_search_by_color_grey(self):
|
||||
qs = self._filter(data={'color': '#f6f6f6'})
|
||||
filter_ = qs['query']['bool']['filter']
|
||||
|
@ -1081,6 +1093,14 @@ class TestSearchParameterFilter(FilterTestsBase):
|
|||
self._filter(data={'color': '#gggggg'})
|
||||
assert context.exception.detail == ['Invalid "color" parameter.']
|
||||
|
||||
with self.assertRaises(serializers.ValidationError) as context:
|
||||
self._filter(data={'color': '#$(@#*)'})
|
||||
assert context.exception.detail == ['Invalid "color" parameter.']
|
||||
|
||||
with self.assertRaises(serializers.ValidationError) as context:
|
||||
self._filter(data={'color': ' '})
|
||||
assert context.exception.detail == ['Invalid "color" parameter.']
|
||||
|
||||
def test_search_by_color_luminosity_extremes(self):
|
||||
qs = self._filter(data={'color': '080603'})
|
||||
filter_ = qs['query']['bool']['filter']
|
||||
|
|
Загрузка…
Ссылка в новой задаче