Skip to content

Commit efabe3e

Browse files
committed
made some cleanup in code for semver
1 parent 032756c commit efabe3e

File tree

8 files changed

+207
-194
lines changed

8 files changed

+207
-194
lines changed

splitio/models/grammar/condition.py

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -124,10 +124,7 @@ def from_raw(raw_condition):
124124
for raw_partition in raw_condition['partitions']
125125
]
126126

127-
try:
128-
matcher_objects = [matchers.from_raw(x) for x in raw_condition['matcherGroup']['matchers']]
129-
except MatcherNotFoundException as e:
130-
raise MatcherNotFoundException(str(e))
127+
matcher_objects = [matchers.from_raw(x) for x in raw_condition['matcherGroup']['matchers']]
131128

132129
combiner = _MATCHER_COMBINERS[raw_condition['matcherGroup']['combiner']]
133130
label = raw_condition.get('label')

splitio/models/grammar/matchers/semver.py

Lines changed: 10 additions & 164 deletions
Original file line numberDiff line numberDiff line change
@@ -3,168 +3,11 @@
33

44
from splitio.models.grammar.matchers.base import Matcher
55
from splitio.models.grammar.matchers.string import Sanitizer
6+
from splitio.models.grammar.matchers.utils.utils import build_semver_or_none
67

7-
_LOGGER = logging.getLogger(__name__)
8-
9-
def build_semver_or_none(version):
10-
try:
11-
return Semver(version)
12-
except (RuntimeError, ValueError):
13-
_LOGGER.error("Invalid semver version: %s", version)
14-
return None
15-
16-
class Semver(object):
17-
"""Semver class."""
18-
19-
_METADATA_DELIMITER = "+"
20-
_PRE_RELEASE_DELIMITER = "-"
21-
_VALUE_DELIMITER = "."
22-
23-
def __init__(self, version):
24-
"""
25-
Class Initializer
26-
27-
:param version: raw version as read from splitChanges response.
28-
:type version: str
29-
"""
30-
self._major = 0
31-
self._minor = 0
32-
self._patch = 0
33-
self._pre_release = []
34-
self._is_stable = False
35-
self.version = ""
36-
self._metadata = ""
37-
self._parse(version)
38-
39-
40-
def _parse(self, version):
41-
"""
42-
Parse the string in self.version to update the other internal variables
43-
"""
44-
without_metadata = self._extract_metadata(version)
45-
index = without_metadata.find(self._PRE_RELEASE_DELIMITER)
46-
if index == -1:
47-
self._is_stable = True
48-
else:
49-
pre_release_data = without_metadata[index+1:]
50-
if pre_release_data == "":
51-
raise RuntimeError("Pre-release is empty despite delimiter exists: " + version)
52-
53-
without_metadata = without_metadata[:index]
54-
for pre_digit in pre_release_data.split(self._VALUE_DELIMITER):
55-
if pre_digit.isnumeric():
56-
pre_digit = str(int(pre_digit))
57-
self._pre_release.append(pre_digit)
58-
59-
self._set_components(without_metadata)
60-
61-
def _extract_metadata(self, version):
62-
"""
63-
Check if there is any metadata characters in self.version.
64-
65-
:returns: The semver string without the metadata
66-
:rtype: str
67-
"""
68-
index = version.find(self._METADATA_DELIMITER)
69-
if index == -1:
70-
return version
71-
72-
self._metadata = version[index+1:]
73-
if self._metadata == "":
74-
raise RuntimeError("Metadata is empty despite delimiter exists: " + version)
75-
76-
return version[:index]
77-
78-
def _set_components(self, version):
79-
"""
80-
Set the major, minor and patch internal variables based on string passed.
81-
82-
:param version: raw version containing major.minor.patch numbers.
83-
:type version: str
84-
"""
858

86-
parts = version.split(self._VALUE_DELIMITER)
87-
if len(parts) != 3 or not (parts[0].isnumeric() and parts[1].isnumeric() and parts[2].isnumeric()):
88-
raise RuntimeError("Unable to convert to Semver, incorrect format: " + version)
89-
90-
self._major = int(parts[0])
91-
self._minor = int(parts[1])
92-
self._patch = int(parts[2])
93-
94-
self.version = "{major}{DELIMITER}{minor}{DELIMITER}{patch}".format(major = self._major, DELIMITER = self._VALUE_DELIMITER,
95-
minor = self._minor, patch = self._patch)
96-
self.version += "{DELIMITER}{pre_release}".format(DELIMITER=self._PRE_RELEASE_DELIMITER,
97-
pre_release = '.'.join(self._pre_release)) if len(self._pre_release) > 0 else ""
98-
self.version += "{DELIMITER}{metadata}".format(DELIMITER=self._METADATA_DELIMITER, metadata = self._metadata) if self._metadata != "" else ""
99-
100-
def compare(self, to_compare):
101-
"""
102-
Compare the current Semver object to a given Semver object, return:
103-
0: if self == passed
104-
1: if self > passed
105-
-1: if self < passed
106-
107-
:param to_compare: a Semver object
108-
:type to_compare: splitio.models.grammar.matchers.semver.Semver
109-
110-
:returns: integer based on comparison
111-
:rtype: int
112-
"""
113-
if self.version == to_compare.version:
114-
return 0
115-
116-
# Compare major, minor, and patch versions numerically
117-
result = self._compare_vars(self._major, to_compare._major)
118-
if result != 0:
119-
return result
120-
121-
result = self._compare_vars(self._minor, to_compare._minor)
122-
if result != 0:
123-
return result
124-
125-
result = self._compare_vars(self._patch, to_compare._patch)
126-
if result != 0:
127-
return result
128-
129-
if not self._is_stable and to_compare._is_stable:
130-
return -1
131-
elif self._is_stable and not to_compare._is_stable:
132-
return 1
133-
134-
# Compare pre-release versions lexically
135-
min_length = min(len(self._pre_release), len(to_compare._pre_release))
136-
for i in range(min_length):
137-
if self._pre_release[i] == to_compare._pre_release[i]:
138-
continue
139-
140-
if self._pre_release[i].isnumeric() and to_compare._pre_release[i].isnumeric():
141-
return self._compare_vars(int(self._pre_release[i]), int(to_compare._pre_release[i]))
142-
143-
return self._compare_vars(self._pre_release[i], to_compare._pre_release[i])
144-
145-
# Compare lengths of pre-release versions
146-
return self._compare_vars(len(self._pre_release), len(to_compare._pre_release))
9+
_LOGGER = logging.getLogger(__name__)
14710

148-
def _compare_vars(self, var1, var2):
149-
"""
150-
Compare 2 variables and return int as follows:
151-
0: if var1 == var2
152-
1: if var1 > var2
153-
-1: if var1 < var2
154-
155-
:param var1: any object accept ==, < or > operators
156-
:type var1: str/int
157-
:param var2: any object accept ==, < or > operators
158-
:type var2: str/int
159-
160-
:returns: integer based on comparison
161-
:rtype: int
162-
"""
163-
if var1 == var2:
164-
return 0
165-
if var1 > var2:
166-
return 1
167-
return -1
16811

16912
class EqualToSemverMatcher(Matcher):
17013
"""A matcher for Semver equal to."""
@@ -209,7 +52,7 @@ def _match(self, key, attributes=None, context=None):
20952

21053
def __str__(self):
21154
"""Return string Representation."""
212-
return 'equal semver {data}'.format(data=self._data)
55+
return f'equal semver {self._data}'
21356

21457
def _add_matcher_specific_properties_to_json(self):
21558
"""Add matcher specific properties to base dict before returning it."""
@@ -258,12 +101,13 @@ def _match(self, key, attributes=None, context=None):
258101

259102
def __str__(self):
260103
"""Return string Representation."""
261-
return 'greater than or equal to semver {data}'.format(data=self._data)
104+
return f'greater than or equal to semver {self._data}'
262105

263106
def _add_matcher_specific_properties_to_json(self):
264107
"""Add matcher specific properties to base dict before returning it."""
265108
return {'matcherType': 'GREATER_THAN_OR_EQUAL_TO_SEMVER', 'stringMatcherData': self._data}
266109

110+
267111
class LessThanOrEqualToSemverMatcher(Matcher):
268112
"""A matcher for Semver less than or equal to."""
269113

@@ -307,12 +151,13 @@ def _match(self, key, attributes=None, context=None):
307151

308152
def __str__(self):
309153
"""Return string Representation."""
310-
return 'less than or equal to semver {data}'.format(data=self._data)
154+
return f'less than or equal to semver {self._data}'
311155

312156
def _add_matcher_specific_properties_to_json(self):
313157
"""Add matcher specific properties to base dict before returning it."""
314158
return {'matcherType': 'LESS_THAN_OR_EQUAL_TO_SEMVER', 'stringMatcherData': self._data}
315159

160+
316161
class BetweenSemverMatcher(Matcher):
317162
"""A matcher for Semver between."""
318163

@@ -363,6 +208,7 @@ def _add_matcher_specific_properties_to_json(self):
363208
"""Add matcher specific properties to base dict before returning it."""
364209
return {'matcherType': 'BETWEEN_SEMVER', 'betweenStringMatcherData': self._data}
365210

211+
366212
class InListSemverMatcher(Matcher):
367213
"""A matcher for Semver in list."""
368214

@@ -374,8 +220,8 @@ def _build(self, raw_matcher):
374220
:type raw_matcher: dict
375221
"""
376222
self._data = raw_matcher['whitelistMatcherData']['whitelist']
377-
semver_list = [build_semver_or_none(item) if item is not None else None for item in self._data]
378-
self._semver_list = frozenset([item.version for item in semver_list])
223+
semver_list = [build_semver_or_none(item) for item in self._data if item]
224+
self._semver_list = frozenset([item.version for item in semver_list if item])
379225

380226
def _match(self, key, attributes=None, context=None):
381227
"""

splitio/models/grammar/matchers/utils/__init__.py

Whitespace-only changes.

0 commit comments

Comments
 (0)