Skip to content

Commit 1e35d2b

Browse files
committed
[UT] Fixed multivalue function call
1 parent 647b235 commit 1e35d2b

File tree

2 files changed

+86
-63
lines changed

2 files changed

+86
-63
lines changed

libs/element.py

Lines changed: 80 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -59,9 +59,11 @@ def __init__(self, expression, func=None):
5959
:param expression: mathematical expression as string
6060
"""
6161
# Validate on expression and raise exception if not true
62+
expression = expression.replace(" ", "")
6263
if not expression:
6364
raise NoExpressionException("The expression was not passed")
6465

66+
# TODO: comment
6567
self._mathematical_functions = {
6668
name: val for name, val in getmembers(math) if type(val).__name__ == "builtin_function_or_method"
6769
}
@@ -72,7 +74,12 @@ def __init__(self, expression, func=None):
7274
name: val for name, val in getmembers(math) if type(val).__name__ == "float"
7375
}
7476

75-
self._func = func
77+
self._func = None
78+
if func:
79+
if func not in self._mathematical_functions:
80+
raise UnsupportedMathematicalFunctionException("We do not support '{}' function".format(self._func))
81+
self._func = self._mathematical_functions.get(func)
82+
7683
self._expression = []
7784

7885
bracket_level = 0
@@ -81,8 +88,9 @@ def __init__(self, expression, func=None):
8188
bracket_closed = False
8289
bracket_content = []
8390
self._comparison_operation = False
91+
self._multivalue = False
8492

85-
# Validate expression on comparison operation and raise exception if it is not valid format
93+
# Validate expression on comparison operation and raise exception if it has not valid format
8694
previous_is_comparison = False
8795
for i, v in enumerate(expression):
8896
if v in self.COMPARISON_OPERATIONS:
@@ -108,9 +116,17 @@ def __init__(self, expression, func=None):
108116
else:
109117
raise ExpressionFormatException("After comparison operation expression or number are expected")
110118

111-
item = []
119+
# Look for multivalue expression
120+
if "(" not in expression and ")" not in expression and "," in expression:
121+
if not self._func:
122+
raise ExpressionFormatException("Commas allowed only in function calls.")
123+
parts = expression.split(",")
124+
self._expression = [Element(i) for i in parts]
125+
self._multivalue = True
126+
return
112127

113128
# Validate format expression and raise exception if it is not valid
129+
item = []
114130
for i in expression:
115131
if bracket_closed:
116132
if i not in self.MATH_ACTIONS and i != ")":
@@ -186,60 +202,38 @@ def __str__(self):
186202
data=", ".join(result)
187203
)
188204

189-
def value(self):
190-
"""
191-
Method for expression calculation
192-
:return: calculate value
193-
"""
194-
operation = None
195-
first_negative = False
196-
197-
# Validate mathematical operations and calculate nested expressions
198-
last_operation = None
199-
for i, v in enumerate(self._expression):
200-
if isinstance(v, Element):
201-
self._expression[i] = v.value()
202-
if last_operation and v in self.MATH_ACTIONS:
203-
raise DoubleOperationException("'{so}' operation follows '{fo}'".format(
204-
so=last_operation,
205-
fo=v
206-
))
207-
if v in self.MATH_ACTIONS:
208-
last_operation = v
209-
else:
210-
last_operation = None
211-
212-
# Validate on comparison operation
205+
def _calculate_boolean_expression(self):
213206
boolean_value = True
214-
if self._comparison_operation:
215-
for i, v in enumerate(self._expression):
216-
if isinstance(v, str):
217-
if v == ">=":
218-
if not self._expression[i - 1] >= self._expression[i + 1]:
219-
boolean_value = False
220-
elif v == "<=":
221-
if not self._expression[i - 1] <= self._expression[i + 1]:
222-
boolean_value = False
223-
elif v == "==":
224-
if not self._expression[i - 1] == self._expression[i + 1]:
225-
boolean_value = False
226-
elif v == "<":
227-
if not self._expression[i - 1] < self._expression[i + 1]:
228-
boolean_value = False
229-
elif v == ">":
230-
if not self._expression[i - 1] > self._expression[i + 1]:
231-
boolean_value = False
232-
elif v in ("!=", "<>",):
233-
if not self._expression[i - 1] != self._expression[i + 1]:
234-
boolean_value = False
235-
else:
236-
raise UnsupportedMathematicalOperationException("We do not support '{}' operation".format(v))
237-
238-
if not boolean_value:
239-
return boolean_value
207+
for i, v in enumerate(self._expression):
208+
if isinstance(v, str):
209+
if v == ">=":
210+
if not self._expression[i - 1] >= self._expression[i + 1]:
211+
boolean_value = False
212+
elif v == "<=":
213+
if not self._expression[i - 1] <= self._expression[i + 1]:
214+
boolean_value = False
215+
elif v == "==":
216+
if not self._expression[i - 1] == self._expression[i + 1]:
217+
boolean_value = False
218+
elif v == "<":
219+
if not self._expression[i - 1] < self._expression[i + 1]:
220+
boolean_value = False
221+
elif v == ">":
222+
if not self._expression[i - 1] > self._expression[i + 1]:
223+
boolean_value = False
224+
elif v in ("!=", "<>",):
225+
if not self._expression[i - 1] != self._expression[i + 1]:
226+
boolean_value = False
227+
else:
228+
raise UnsupportedMathematicalOperationException("We do not support '{}' operation".format(v))
240229

241-
return boolean_value
230+
if not boolean_value:
231+
return boolean_value
232+
return boolean_value
242233

234+
def _calculate_mathematical_expression(self):
235+
operation = None
236+
first_negative = False
243237
# Validate first negative numbers in expression
244238
if self._expression[0] == "-":
245239
first_negative = True
@@ -301,10 +295,37 @@ def value(self):
301295

302296
# Validate on mathematical function
303297
if self._func:
304-
math_func = self._mathematical_functions.get(self._func)
305-
if math_func:
306-
value = math_func(value)
307-
else:
308-
raise UnsupportedMathematicalFunctionException("We do not support '{}' function".format(self._func))
298+
value = self._func(value)
309299

310300
return value
301+
302+
def value(self):
303+
"""
304+
Method for expression calculation
305+
:return: calculate value
306+
"""
307+
308+
# Validate mathematical operations and calculate nested expressions
309+
last_operation = None
310+
for i, v in enumerate(self._expression):
311+
if isinstance(v, Element):
312+
self._expression[i] = v.value()
313+
if last_operation and v in self.MATH_ACTIONS:
314+
raise DoubleOperationException("'{so}' operation follows '{fo}'".format(
315+
so=last_operation,
316+
fo=v
317+
))
318+
if v in self.MATH_ACTIONS:
319+
last_operation = v
320+
else:
321+
last_operation = None
322+
323+
# Evaluate comparison expression
324+
if self._comparison_operation:
325+
return self._calculate_boolean_expression()
326+
327+
# Evaluate multi-value expression
328+
if self._multivalue:
329+
return self._func(*self._expression)
330+
331+
return self._calculate_mathematical_expression()

pycalc

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
#!/usr/bin/env python3
22

33
import argparse
4-
from libs.element import Element
4+
from libs.element import Element, BaseExpressionException
55

66
if __name__ == '__main__':
77
parser = argparse.ArgumentParser(description="")
@@ -10,6 +10,8 @@ if __name__ == '__main__':
1010

1111
args = parser.parse_args()
1212

13-
expression = Element(expression=args.EXPRESSION)
14-
# print(str(expression))
15-
print(expression.value())
13+
try:
14+
expression = Element(expression=args.EXPRESSION)
15+
print(expression.value())
16+
except BaseExpressionException as exc:
17+
print("ERROR: {}".format(str(exc)))

0 commit comments

Comments
 (0)