Skip to content

Commit ec85509

Browse files
authored
Merge pull request #510 from splitio/semver-greater-equalto-matcher
added greater or equal to semver matcher
2 parents 2d8979e + cdb1abc commit ec85509

File tree

3 files changed

+95
-5
lines changed

3 files changed

+95
-5
lines changed

splitio/models/grammar/matchers/__init__.py

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
from splitio.models.grammar.matchers.string import ContainsStringMatcher, \
99
EndsWithMatcher, RegexMatcher, StartsWithMatcher, WhitelistMatcher
1010
from splitio.models.grammar.matchers.misc import BooleanMatcher, DependencyMatcher
11-
from splitio.models.grammar.matchers.semver import EqualToSemverMatcher
11+
from splitio.models.grammar.matchers.semver import EqualToSemverMatcher, GreaterThanOrEqualToSemverMatcher
1212

1313

1414
MATCHER_TYPE_ALL_KEYS = 'ALL_KEYS'
@@ -29,7 +29,7 @@
2929
MATCHER_TYPE_EQUAL_TO_BOOLEAN = 'EQUAL_TO_BOOLEAN'
3030
MATCHER_TYPE_MATCHES_STRING = 'MATCHES_STRING'
3131
MATCHER_TYPE_EQUAL_TO_SEMVER = 'EQUAL_TO_SEMVER'
32-
32+
MATCHER_GREATER_THAN_OR_EQUAL_TO_SEMVER = 'GREATER_THAN_OR_EQUAL_TO_SEMVER'
3333

3434
_MATCHER_BUILDERS = {
3535
MATCHER_TYPE_ALL_KEYS: AllKeysMatcher,
@@ -49,11 +49,10 @@
4949
MATCHER_TYPE_IN_SPLIT_TREATMENT: DependencyMatcher,
5050
MATCHER_TYPE_EQUAL_TO_BOOLEAN: BooleanMatcher,
5151
MATCHER_TYPE_MATCHES_STRING: RegexMatcher,
52-
MATCHER_TYPE_EQUAL_TO_SEMVER: EqualToSemverMatcher
53-
52+
MATCHER_TYPE_EQUAL_TO_SEMVER: EqualToSemverMatcher,
53+
MATCHER_GREATER_THAN_OR_EQUAL_TO_SEMVER: GreaterThanOrEqualToSemverMatcher
5454
}
5555

56-
5756
def from_raw(raw_matcher):
5857
"""
5958
Parse a condition from a JSON portion of splitChanges.

splitio/models/grammar/matchers/semver.py

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -214,3 +214,52 @@ def __str__(self):
214214
def _add_matcher_specific_properties_to_json(self):
215215
"""Add matcher specific properties to base dict before returning it."""
216216
return {'matcherType': 'EQUAL_TO_SEMVER', 'stringMatcherData': self._data}
217+
218+
class GreaterThanOrEqualToSemverMatcher(Matcher):
219+
"""A matcher for Semver greater than or equal to."""
220+
221+
def _build(self, raw_matcher):
222+
"""
223+
Build a GreaterThanOrEqualToSemverMatcher.
224+
225+
:param raw_matcher: raw matcher as fetched from splitChanges response.
226+
:type raw_matcher: dict
227+
"""
228+
self._data = raw_matcher.get('stringMatcherData')
229+
self._semver = Semver.build(self._data)
230+
231+
def _match(self, key, attributes=None, context=None):
232+
"""
233+
Evaluate user input against a matcher and return whether the match is successful.
234+
235+
:param key: User key.
236+
:type key: str.
237+
:param attributes: Custom user attributes.
238+
:type attributes: dict.
239+
:param context: Evaluation context
240+
:type context: dict
241+
242+
:returns: Wheter the match is successful.
243+
:rtype: bool
244+
"""
245+
if self._data is None or self._semver is None:
246+
_LOGGER.error("stringMatcherData is required for GREATER_THAN_OR_EQUAL_TO_SEMVER matcher type")
247+
return False
248+
249+
matching_data = Sanitizer.ensure_string(self._get_matcher_input(key, attributes))
250+
if matching_data is None:
251+
return False
252+
253+
matching_semver = Semver.build(matching_data)
254+
if matching_semver is None:
255+
return False
256+
257+
return matching_semver.compare(self._semver) in [0, 1]
258+
259+
def __str__(self):
260+
"""Return string Representation."""
261+
return 'greater than or equal to semver {data}'.format(data=self._data)
262+
263+
def _add_matcher_specific_properties_to_json(self):
264+
"""Add matcher specific properties to base dict before returning it."""
265+
return {'matcherType': 'GREATER_THAN_OR_EQUAL_TO_SEMVER', 'stringMatcherData': self._data}

tests/models/grammar/test_matchers.py

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -926,3 +926,45 @@ def test_to_str(self):
926926
"""Test that the object serializes to str properly."""
927927
as_str = matchers.EqualToSemverMatcher(self.raw)
928928
assert str(as_str) == "equal semver 2.1.8"
929+
930+
class GreaterThanOrEqualToSemverMatcherTests(MatcherTestsBase):
931+
"""Semver greater or equalto matcher test cases."""
932+
933+
raw = {
934+
'negate': False,
935+
'matcherType': 'GREATER_THAN_OR_EQUAL_TO_SEMVER',
936+
'stringMatcherData': "2.1.8"
937+
}
938+
939+
def test_from_raw(self, mocker):
940+
"""Test parsing from raw json/dict."""
941+
parsed = matchers.from_raw(self.raw)
942+
assert isinstance(parsed, matchers.GreaterThanOrEqualToSemverMatcher)
943+
assert parsed._data == "2.1.8"
944+
assert isinstance(parsed._semver, Semver)
945+
assert parsed._semver._major == 2
946+
assert parsed._semver._minor == 1
947+
assert parsed._semver._patch == 8
948+
assert parsed._semver._pre_release == []
949+
950+
def test_matcher_behaviour(self, mocker):
951+
"""Test if the matcher works properly."""
952+
parsed = matchers.from_raw(self.raw)
953+
assert parsed._match("2.1.8+rc")
954+
assert parsed._match("2.1.8")
955+
assert parsed._match("2.1.11")
956+
assert not parsed._match("2.1.5")
957+
assert not parsed._match("2.1.5-rc1")
958+
assert not parsed._match(None)
959+
assert not parsed._match("semver")
960+
961+
def test_to_json(self):
962+
"""Test that the object serializes to JSON properly."""
963+
as_json = matchers.GreaterThanOrEqualToSemverMatcher(self.raw).to_json()
964+
assert as_json['matcherType'] == 'GREATER_THAN_OR_EQUAL_TO_SEMVER'
965+
assert as_json['stringMatcherData'] == "2.1.8"
966+
967+
def test_to_str(self):
968+
"""Test that the object serializes to str properly."""
969+
as_str = matchers.GreaterThanOrEqualToSemverMatcher(self.raw)
970+
assert str(as_str) == "greater than or equal to semver 2.1.8"

0 commit comments

Comments
 (0)