diff --git a/README.md b/README.md
new file mode 100644
index 00000000..e5e8d9ac
--- /dev/null
+++ b/README.md
@@ -0,0 +1 @@
+# pycalc
diff --git a/final_task/.idea/final_task.iml b/final_task/.idea/final_task.iml
new file mode 100644
index 00000000..67116063
--- /dev/null
+++ b/final_task/.idea/final_task.iml
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/final_task/.idea/inspectionProfiles/Project_Default.xml b/final_task/.idea/inspectionProfiles/Project_Default.xml
new file mode 100644
index 00000000..5554c50f
--- /dev/null
+++ b/final_task/.idea/inspectionProfiles/Project_Default.xml
@@ -0,0 +1,114 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/final_task/.idea/misc.xml b/final_task/.idea/misc.xml
new file mode 100644
index 00000000..a43ec93e
--- /dev/null
+++ b/final_task/.idea/misc.xml
@@ -0,0 +1,4 @@
+
+
+
+
\ No newline at end of file
diff --git a/final_task/.idea/modules.xml b/final_task/.idea/modules.xml
new file mode 100644
index 00000000..50b3aa4b
--- /dev/null
+++ b/final_task/.idea/modules.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/final_task/.idea/vcs.xml b/final_task/.idea/vcs.xml
new file mode 100644
index 00000000..6c0b8635
--- /dev/null
+++ b/final_task/.idea/vcs.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/final_task/.idea/workspace.xml b/final_task/.idea/workspace.xml
new file mode 100644
index 00000000..3f362a23
--- /dev/null
+++ b/final_task/.idea/workspace.xml
@@ -0,0 +1,262 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ divi
+ err
+ ('err
+ nt('err
+ pycalc.main
+ # print('ER
+ pycalc.py_calculator
+ rint('ERRO
+ invalid
+ invalid ar
+
+ print
+ except TypeError
+ try
+ enu
+ ss
+ skob
+ # #
+ operator
+ splitset
+ funcset
+ operset
+ #unaryexp
+ funclist
+ rang
+ xpr
+ """
+
+
+ pycalc.main
+ print('ER
+ pycalc.calc
+
+ # print
+ lt
+ brkt
+ #
+ unaryexp
+ xprstr
+ """
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/final_task/func.py b/final_task/func.py
new file mode 100644
index 00000000..27c02152
--- /dev/null
+++ b/final_task/func.py
@@ -0,0 +1,2 @@
+def main():
+ return 666
diff --git a/final_task/funcx.py b/final_task/funcx.py
new file mode 100644
index 00000000..ecd53439
--- /dev/null
+++ b/final_task/funcx.py
@@ -0,0 +1,3 @@
+def main(x):
+ x = (x + x) * x
+ return x
diff --git a/final_task/funcxy.py b/final_task/funcxy.py
new file mode 100644
index 00000000..015c6749
--- /dev/null
+++ b/final_task/funcxy.py
@@ -0,0 +1,3 @@
+def main(x, y):
+ x = (x + y) * 2
+ return x
diff --git a/final_task/mytest.py b/final_task/mytest.py
new file mode 100644
index 00000000..09cab01e
--- /dev/null
+++ b/final_task/mytest.py
@@ -0,0 +1,28 @@
+import unittest
+import math
+from math import *
+import pycalc
+
+# -15//2=-8
+# 0-15//2=-7
+# 0+15//2=7
+# 0- -15//2=8
+# 0+-(-15)//2=7
+
+print("-15//2=-8", ">>>>", pycalc.calc("-15//2"))
+print("0-15//2=-7", ">>>>", pycalc.calc("0-15//2"))
+print("0+15//2=7", ">>>>", pycalc.calc("0+15//2"))
+print("0- -15//2=8", ">>>>", pycalc.calc("0- -15//2"))
+print("0+-(-15)//2=7", ">>>>", pycalc.calc("0+-(-15)//2"))
+
+print("2+-(3+4)", ">>>>", pycalc.calc("2+-(3+4)"))
+print("2--(3+4)", ">>>>", pycalc.calc("2--(3+4)"))
+print("2/-sin(3+4)", ">>>>", pycalc.calc("2/-sin(3+4)"))
+print("2+-(3)+4", ">>>>", pycalc.calc("2+-(3)+4"))
+print("2+-3/2)", ">>>>", pycalc.calc("2+-3/2)"))
+
+print("2+2^3^4", ">>>>", pycalc.brackets4exp("2+2^3^4"))
+print("2+2^1-3^4", ">>>>", pycalc.brackets4exp("2+2^1-3^4"))
+print("2+2^3^4/2", ">>>>", pycalc.brackets4exp("2+2^3^4/2"))
+print("2+2^3^4/2+1", ">>>>", pycalc.brackets4exp("2+2^3^4/2+1"))
+print("(2+2)^(3-1)^4+2", ">>>>", pycalc.brackets4exp("(2+2)^(3-1)^4+2"))
diff --git a/final_task/pycalc.py b/final_task/pycalc.py
new file mode 100644
index 00000000..b3df6ebb
--- /dev/null
+++ b/final_task/pycalc.py
@@ -0,0 +1,353 @@
+import argparse
+import math
+from math import *
+import operator
+from operator import *
+import importlib
+import importlib.util
+
+split = ('^', '/', '*', '%', '-', '+', '=', '<', '>', '!', '(', ')', ',')
+# Good style
+# funclst = [attr in dir(math) if callable(getattr(math, attr))]
+# fundic = dict([(attr, getattr(math, attr)) for attr in dir(math) if callable(getattr(math, attr))])
+# callable false pi, e, tau
+funclst = dir(math) + ['abs', 'round', 'sum']
+funcdic = math.__dict__
+operdic = {
+ '+': add,
+ '-': sub,
+ '*': mul,
+ '/': truediv,
+ '//': floordiv,
+ '%': mod,
+ '^': pow,
+ '==': eq,
+ '<=': le,
+ '>=': ge,
+ '<': lt,
+ '>': gt,
+ '!=': ne,
+ 'abs': abs,
+ 'round': round,
+ 'sum': sum
+ }
+funcdic.update(operdic)
+oper = ['^', '//', '/', '*', '%', '-', '+', '==', '<=', '>=', '<', '>', '!=']
+
+
+def parsecmd():
+ """парсинг командной строки"""
+ ap = argparse.ArgumentParser(description='Pure-python command-line calculator.')
+ ap.add_argument('EXPRESSION', type=str, help='expression string to evalute')
+ ap.add_argument('-m', '--MODULE', type=str, help='use modules MODULE [MODULE...] additional modules to use')
+ args = ap.parse_args()
+ xprstr = args.EXPRESSION
+ module = args.MODULE
+ return xprstr, module
+
+
+def addfunc(module):
+ """добавление новой функцию из модуля (module)"""
+ if module is not None: # если введено имя модуля
+ try:
+ spec = importlib.util.find_spec(module)
+ except ImportError:
+ raise ValueError('ERROR: module ', module, 'not found, or unknown symbol')
+ if spec is None: # проверка возможности импорта модуля
+ raise ValueError('ERROR: unknown function or module ', module, 'not found')
+ else:
+ newfunc = importlib.import_module(module) # импортирование нового модуля
+ funcdic[module] = newfunc.main
+ funclst.append(module)
+ return
+
+
+def unaryexp(xprstr):
+ """добавление в строку выражения скобок для возведение в степень типа pi^-pi >>> pi^(-pi)"""
+ right = len(xprstr)
+ for i in range(xprstr.count('^')):
+ right = xprstr.rindex('^', 0, right) # поиск справа первого ^
+ if xprstr[right] == '^' and xprstr[right+1] == '-': # если возведение в степень типа ^-pi добавить скобки
+ xprstr = xprstr[:right+1]+'('+xprstr[right+1:] # добавляем левую (
+ right = right + 3
+ # поиск строки справа от ^
+ brkt = 0
+ j = 0
+ while j < len(xprstr[right:]) or (brkt == 0 and xprstr[j] == ')'):
+ if xprstr[j] == '(':
+ brkt = brkt + 1
+ if xprstr[j] == ')':
+ brkt = brkt - 1
+ if brkt == 0 and xprstr[j] in oper:
+ j = j - 1
+ break
+ j = j + 1
+ xprstr = xprstr[:right + 1 + j] + ')' + xprstr[right + 1 + j:]
+ return(xprstr)
+
+
+def brackets4exp(xprstr):
+ """добавление в строку выражения скобок для возведение в степень типа 2^3^4 >>> 2^(3^4)"""
+ right = len(xprstr)
+ for i in range(xprstr.count('^')):
+ right = xprstr.rindex('^', 0, right) # находим позицию самого правого знака ^
+ if xprstr[:right].count('^') == 0:
+ break
+ left = xprstr.rindex('^', 0, right)+1 # находим позицию следущего правого знака ^
+ tmp = xprstr[left:right] # строка между ^ ... ^
+ tmpset = set(tmp)
+ if (tmp[0] == '(' and tmp[-1] == ')') or (tmpset.isdisjoint(set(split))): # надо скобки
+ xprstr = xprstr[:left]+'('+xprstr[left:] # вставляем левую скобку
+ right = right + 1
+ # поиск строки справа от ^
+ brkt = 0
+ for j, data in enumerate(xprstr[right:]):
+ if data == '(':
+ brkt = brkt + 1
+ if data == ')':
+ brkt = brkt - 1
+ if brkt == 0 and data in ['+', '-', '*', '/']:
+ j = j-1
+ break
+ if brkt == 0 and data == ')':
+ break
+ xprstr = xprstr[:right+1+j]+')'+xprstr[right + 1 + j:]
+ else: # НЕ надо скобки
+ right = left
+ return(xprstr)
+
+
+def preparse(xprstr):
+ """очистка строки выражения от мусора, повторных знаков и пробелов"""
+ xprset = set(xprstr)
+ operset = set(oper)
+ operset.add(' ')
+ if xprset.issubset(operset): # проверка если выражение сосотоит только из операторов или пробелов
+ raise ValueError('ERROR: no digits or functions in expression')
+ if xprstr.count('(') != xprstr.count(')') or len(xprstr) == 0: # проверка скобок в строке
+ raise ValueError('ERROR: brackets are not balanced')
+ # устранение пробелов с операторами и повторов операторов
+ while xprstr.count(' ') > 0 or \
+ xprstr.count('++') > 0 or \
+ xprstr.count('-+') > 0 or \
+ xprstr.count(' *') > 0 or \
+ xprstr.count('* ') > 0 or \
+ xprstr.count(' +') > 0 or \
+ xprstr.count('+ ') > 0 or \
+ xprstr.count(' -') > 0 or \
+ xprstr.count('- ') > 0 or \
+ xprstr.count(', ') > 0:
+ xprstr = xprstr.replace(' ', ' ')
+ xprstr = xprstr.replace('++', '+')
+ xprstr = xprstr.replace('-+', '-')
+ xprstr = xprstr.replace(' *', '*')
+ xprstr = xprstr.replace('* ', '*')
+ xprstr = xprstr.replace(' +', '+')
+ xprstr = xprstr.replace('+ ', '+')
+ xprstr = xprstr.replace(' -', '-')
+ xprstr = xprstr.replace('- ', '-')
+ xprstr = xprstr.replace(', ', ',')
+ if xprstr[0] == '+':
+ xprstr = xprstr[1:]
+ if xprstr.count(' ') > 0: # проверка лишних пробелов
+ raise ValueError('ERROR: useles spaces')
+ # print('PREPARSE', xprstr)
+ return(xprstr)
+
+
+def afterparse(xprlst):
+ """поиск операторов типа <= >= == !=, замена унарнонго - на -1*"""
+ i = 0
+ while i < len(xprlst):
+ if i < len(xprlst)-1:
+ if type(xprlst[i]) == float and xprlst[i+1] == '(': # елсли перед скобкой цифра без оператора 5(
+ raise ValueError('ERROR: digit & ( wihout operator')
+ if xprlst[i] == ')' and type(xprlst[i+1]) == float: # елсли после скобки цифра без оператора (5
+ raise ValueError('ERROR: ) & digit wihout operator')
+ if i == len(xprlst) - 1:
+ break
+ if str(xprlst[i]) + str(xprlst[i+1]) in oper: # '>' + '='
+ xprlst[i+1] = str(xprlst[i]) + str(xprlst[i+1]) # '>='
+ xprlst.pop(i)
+ # унарный минус (-( +-( +-5 +-sin
+ # print('i=', i, '[i]=', xprlst[i])
+ if xprlst[i] == '-' and xprlst[i-1] in oper+['('] and (type(xprlst[i + 1]) == float
+ or xprlst[i + 1] in funclst
+ or xprlst[i + 1] == '-'
+ or xprlst[i + 1] == '('):
+ xprlst[i] = -1
+ xprlst = xprlst[:i + 1] + ['*'] + xprlst[i + 1:]
+ i = i + 1
+ if xprlst[0] == '-':
+ xprlst[0] = -1
+ xprlst.insert(1, '*')
+ # print('AFTERPARSE', *xprlst, sep=' ')
+ return(xprlst)
+
+
+def parse(xprstr):
+ """парсинг строки математического выражения. на выходе список в инфиксной нотации"""
+ word = ''
+ xprlst = []
+ xprstr = preparse(xprstr) # подготовка к парсингу
+ xprstr = unaryexp(xprstr) # добавление скобок для e^-e >>> e^(-e)
+ xprstr = brackets4exp(xprstr) # добавление скобок для 2^3^4 >>> 2^(3^4)
+ # print(xprstr)
+ # разбор строки
+ for i, sym in enumerate(xprstr + ' '): # добавлен дополнительный пробел
+ if sym in split or i == len(xprstr):
+ if word in funclst: # если функция
+ xprlst.append(word)
+ elif word.replace('.', '').isdigit() and word.count('.') < 2: # если цифра
+ xprlst.append(float(word))
+ elif word != '': # если не пусто и непонятно что, возможно это внешняя функция
+ addfunc(word) # попытка импортировать неизвестную функцию
+ xprlst.append(word)
+ xprlst.append(sym)
+ word = ''
+ else:
+ word = word + sym
+ xprlst.pop() # удаляется добавленный пробел
+ # print('PARSE', *xprlst, sep=' ')
+ return xprlst
+
+
+def prior(op1, op2):
+ """сравнивает приоритеты математических опрераторов и функций op1 <= op2, возвращает bool"""
+ operhiest = ['^'] + funclst # 4
+ operhi = ['*'] # 3
+ opermid = ['/', '%', '//'] # 2
+ operlow = ['+', '-'] # 1
+ operlowest = ['(', ')', '==', '<=', '>=', '<', '>', '!=', ','] # 0
+ priorset = [operlowest, operlow, opermid, operhi, operhiest]
+ for i, data in enumerate(priorset):
+ if op1 in data:
+ pr1 = i
+ if op2 in data:
+ pr2 = i
+ return pr1 <= pr2
+
+
+def postfix(xprlst):
+ """преобразование инфиксной нотации в постфиксную
+ на входе список элементов выражения инфиксной нотации, на выходе список элементов постфиксной нотации"""
+ output = []
+ stack = []
+ for i in xprlst:
+ if type(i) == float or type(i) == int: # если цифра то положить на выход
+ output.append(i)
+ elif i == ',': # если , то положить на выход
+ if stack != []:
+ while stack != [] and stack[-1] in oper+funclst and prior(i, stack[-1]):
+ # пока наверху стека оператор с большим или равным приоритетом
+ output.append(stack.pop()) # переложить оператор из стека на выход
+ output.append(i)
+ elif i in oper: # если оператор то положить в стек
+ if stack == []: # если стек пуст, оператор добавить в стек
+ stack.append(i)
+ elif stack[-1] == '(': # если стек содержит ( положить в стек (
+ stack.append(i)
+ else:
+ while stack != [] and stack[-1] in oper+funclst and prior(i, stack[-1]):
+ # пока наверху стека оператор с большим или равным приоритетом
+ output.append(stack.pop()) # переложить оператор из стека на выход
+ stack.append(i) # иначе положить оператор в стек
+ elif i in funclst or i == '(': # если функция или ( то помещаем в стек
+ stack.append(i)
+ elif i == ')':
+ while stack[-1] != '(': # пока верх стека не равен (
+ output.append(stack.pop()) # выталкиваем элемент из стека на выход. удаляя последний элемент в стеке
+ stack.pop() # удаление из стека (
+ stack.reverse()
+ # print('POSTFIX', output, stack )
+ return output + stack
+
+
+def operate(operator, args):
+ """выполняет математическое действие или функцию (operator) со списком аргументов (args)"""
+ global stack # используется в функции evalpostfix
+ # print('OPERATE', operator, 'ARGS', args, 'STACK', stack)
+ try:
+ result = funcdic[operator](*args) # если функция с одним или двумя аргументами типа sin(x), pow(x,y)
+ stack.pop()
+ except TypeError:
+ try:
+ result = funcdic[operator](args) # если функция с аргументом типа список sum(x,y,z,...)
+ stack.pop()
+ except TypeError:
+ try:
+ result = funcdic[operator]() # если функция без аргументов типа pi, e, tau
+ except TypeError:
+ try:
+ result = funcdic[operator] # если внешняя функция без аргументов типа myfunc()
+ if type(result) != float:
+ raise ValueError('ERROR: not float argument for ', operator)
+ except TypeError:
+ raise ValueError('ERROR: invalid argument for ', operator)
+ except ValueError:
+ raise ValueError('ERROR: invalid argument for ', operator)
+ # print('RESULT', result)
+ return result
+
+
+def evalpostfix(xprpstfx):
+ """вычисление выражения в постфиксной нотации (список)"""
+ global stack # используется в функции operate для удаления аргументов из стека
+ stack = []
+ args = []
+ for i in xprpstfx:
+ if i in funclst: # если функция типа sin, pow, sum, tau
+ if len(stack) == 0:
+ args = 0 # функция без аргументов типа pi, e, tau
+ if len(stack) == 1:
+ args = stack[0] # один аргумент функции типа sin(x)
+ if len(stack) > 1:
+ j = len(stack)-2
+ args.append(stack[-1]) # один аргумент функции типа sin(x)
+ while stack[j] == ',': # если в стэке список аргументов разделенных запятой ,
+ args.append(stack[j-1]) # добавить в список агрументов функции типа pow(x,y), sum(x,y,z,...)
+ stack.pop() # удалить из стэка ,
+ stack.pop() # удалить из стэка аргумент
+ j = j - 2
+ args.reverse()
+ # print('OPERATEf', i, 'ARGS', args, 'STACK', stack)
+ stack.append(operate(i, args)) # удаление аргумента из стэка произойдет в функции operate
+ args = []
+
+ elif i in oper: # если оператор типа a + b
+ # print('OPERATEo', i, 'ARGS', *stack[-2:], 'STACK', stack)
+ # print(*stack[-2:])
+ # print(funcdic[i])
+ tmp = funcdic[i](*stack[-2:])
+ stack.pop() # удалить из стэка аргумент a
+ stack.pop() # удалить из стэка аргумент b
+ stack.append(tmp)
+ # print('RESULT', tmp)
+ else:
+ stack.append(i) # если число то добавить его в стэк
+ # print('STACK',stack)
+ return stack[0]
+
+
+def calc(xprstr):
+ """вычисление строки (xprstr) математического выражения"""
+ xprlst = parse(xprstr) # разбор строки вырыжения в список
+ xprlst = afterparse(xprlst)
+ xprlst = postfix(xprlst) # преобразование инфиксного списка в постфиксных список
+ result = evalpostfix(xprlst) # вычисление постфиксного списка
+ print(result)
+ return result
+
+
+def main():
+ try:
+ xprstr, module = parsecmd() # парсинг аргументов командной строки xprstr выражение и module модуль функции
+ addfunc(module) # попытка добавления внешней функции если указана -m module
+ calc(xprstr) # калькулятор. вычисление выражения в строке xprstr
+ except Exception as error:
+ print('ERROR:', error)
+ return
+
+
+if __name__ == '__main__':
+ main()
diff --git a/final_task/setup.py b/final_task/setup.py
index e69de29b..44050196 100644
--- a/final_task/setup.py
+++ b/final_task/setup.py
@@ -0,0 +1,14 @@
+from setuptools import setup
+
+setup(
+ name='pycalc', # Required
+ version='1.0', # Required
+ description='Pure-python command-line calculator.', # Optional
+ url='https://github.com/novash-k/PythonHomework', # Optional
+ author='Konstantin Novash', # Optional
+ author_email='novash.ki@gmail.com', # Optional
+ py_modules=["pycalc"], # Required
+ entry_points={'console_scripts': ['pycalc=pycalc:main', ], },
+ # packages=['pycalc_project'] # Required
+ # python_requires='>3.0, <3.7'
+ )
diff --git a/final_task/test.py b/final_task/test.py
new file mode 100644
index 00000000..aabba562
--- /dev/null
+++ b/final_task/test.py
@@ -0,0 +1,92 @@
+import unittest
+import math
+from math import *
+import pycalc
+
+
+print("2+2^3^4", ">>>>", pycalc.brackets4exp("2+2^3^4"))
+print("2+2^1-3^4", ">>>>", pycalc.brackets4exp("2+2^1-3^4"))
+print("2+2^3^4/2", ">>>>", pycalc.brackets4exp("2+2^3^4/2"))
+print("2+2^3^4/2+1", ">>>>", pycalc.brackets4exp("2+2^3^4/2+1"))
+print("(2+2)^(3-1)^4+2", ">>>>", pycalc.brackets4exp("(2+2)^(3-1)^4+2"))
+
+
+class TestParse(unittest.TestCase):
+
+ def testcases(self):
+ self.assertEqual(pycalc.brackets4exp("2^3^4"), "2^(3^4)")
+ self.assertEqual(pycalc.brackets4exp("2^3^(4+1)"), "2^(3^(4+1))")
+ self.assertEqual(pycalc.brackets4exp("(2+2)^(3-1)^4"), "(2+2)^((3-1)^4)")
+ self.assertEqual(pycalc.brackets4exp("(2+2)^(3-1)^4+2"), "(2+2)^((3-1)^4)+2")
+
+
+class TestPycalc(unittest.TestCase):
+
+ def testcases(self):
+ self.assertEqual(pycalc.calc("-13"), eval("-13"))
+ self.assertEqual(pycalc.calc("6-(-13)"), eval("6-(-13)"))
+ self.assertEqual(pycalc.calc("1---1"), eval("1---1"))
+ self.assertEqual(pycalc.calc("-+---+-1"), eval("-+---+-1"))
+
+ self.assertEqual(pycalc.calc("1+2*2"), eval("1+2*2"))
+ self.assertEqual(pycalc.calc("1+(2+3*2)*3"), eval("1+(2+3*2)*3"))
+ self.assertEqual(pycalc.calc("10*(2+1)"), eval("10*(2+1)"))
+ self.assertEqual(pycalc.calc("10^(2+1)"), eval("10**(2+1)"))
+ self.assertEqual(pycalc.calc("100/3^2"), eval("100/3**2"))
+ self.assertEqual(pycalc.calc("100/3%2^2"), eval("100/3%2**2"))
+
+ self.assertEqual(pycalc.calc("pi+e"), eval("pi+e"))
+ self.assertEqual(pycalc.calc("log(e)"), eval("log(e)"))
+ self.assertEqual(pycalc.calc("sin(pi/2)"), eval("sin(pi/2)"))
+ self.assertEqual(pycalc.calc("log10(100)"), eval("log10(100)"))
+ self.assertEqual(pycalc.calc("sin(pi/2)*111*6"), eval("sin(pi/2)*111*6"))
+ self.assertEqual(pycalc.calc("2*sin(pi/2)"), eval("2*sin(pi/2)"))
+ self.assertEqual(pycalc.calc("abs(-5)"), eval("abs(-5)"))
+ self.assertEqual(pycalc.calc("round(123.456789)"), eval("round(123.456789)"))
+
+ self.assertEqual(pycalc.calc("102%12%7"), eval("102%12%7"))
+ self.assertEqual(pycalc.calc("100/4/3"), eval("100/4/3"))
+ self.assertEqual(pycalc.calc("2^3^4"), eval("2**3**4"))
+
+ self.assertEqual(pycalc.calc("1+2*3==1+2*3"), eval("1+2*3==1+2*3"))
+ self.assertEqual(pycalc.calc("e^5>=e^5+1"), eval("e**5>=e**5+1"))
+ self.assertEqual(pycalc.calc("1+2*4/3+1!=1+2*4/3+2"), eval("1+2*4/3+1!=1+2*4/3+2"))
+
+ self.assertEqual(pycalc.calc("(100)"), eval("(100)"))
+ self.assertEqual(pycalc.calc("666"), eval("666"))
+ self.assertEqual(pycalc.calc("-.1"), eval("-.1"))
+ self.assertEqual(pycalc.calc("1/3"), eval("1/3"))
+ self.assertEqual(pycalc.calc("1.0/3.0"), eval("1.0/3.0"))
+ self.assertEqual(pycalc.calc(".1 * 2.0^56.0"), eval(".1 * 2.0**56.0"))
+ self.assertEqual(pycalc.calc("e^34"), eval("e**34"))
+ self.assertEqual(pycalc.calc("(2.0^(pi/pi+e/e+2.0^0.0))"), eval("(2.0**(pi/pi+e/e+2.0**0.0))"))
+ self.assertEqual(pycalc.calc("(2.0^(pi/pi+e/e+2.0^0.0))^(1.0/3.0)"),
+ eval("(2.0**(pi/pi+e/e+2.0**0.0))**(1.0/3.0)"))
+ self.assertEqual(pycalc.calc("sin(pi/2^1) + log(1*4+2^2+1, 3^2)"),
+ eval("sin(pi/2**1) + log(1*4+2**2+1, 3**2)"))
+ self.assertEqual(pycalc.calc("10*e^0*log10(.4 -5/ -0.1-10) - -abs(-53/10) + -5"),
+ eval("10*e**0*log10(.4 -5/ -0.1-10) - -abs(-53/10) + -5"))
+ self.assertEqual(pycalc.calc("sin(-cos(-sin(3.0)-cos(-sin(-3.0*5.0)-sin(cos(log10(43.0))))"
+ "+cos(sin(sin(34.0-2.0^2.0))))--cos(1.0)--cos(0.0)^3.0)"),
+ eval("sin(-cos(-sin(3.0)-cos(-sin(-3.0*5.0)-sin(cos(log10(43.0))))"
+ "+cos(sin(sin(34.0-2.0**2.0))))--cos(1.0)--cos(0.0)**3.0)"))
+ self.assertEqual(pycalc.calc("2.0^(2.0^2.0*2.0^2.0)"), eval("2.0**(2.0**2.0*2.0**2.0)"))
+ self.assertEqual(pycalc.calc("sin(e^log(e^e^sin(23.0),45.0) + cos(3.0+log10(e^-e)))"),
+ eval("sin(e**log(e**e**sin(23.0),45.0) + cos(3.0+log10(e**-e)))"))
+
+ def testerrorscases(self):
+ self.assertRaises(ValueError, pycalc.calc, "+")
+ self.assertRaises(TypeError, pycalc.calc, "1-")
+ self.assertRaises(ValueError, pycalc.calc, "1 2")
+ self.assertRaises(ValueError, pycalc.calc, "ee")
+ self.assertRaises(TypeError, pycalc.calc, "==7")
+ self.assertRaises(ValueError, pycalc.calc, "1 + 2(3 * 4))")
+ self.assertRaises(ValueError, pycalc.calc, "((1+2)")
+ self.assertRaises(ValueError, pycalc.calc, "1 + 1 2 3 4 5 6 ")
+ self.assertRaises(ValueError, pycalc.calc, "log100(100)")
+ self.assertRaises(ValueError, pycalc.calc, "------")
+ self.assertRaises(ValueError, pycalc.calc, "5 > = 6")
+ self.assertRaises(ValueError, pycalc.calc, "5 / / 6")
+ self.assertRaises(TypeError, pycalc.calc, "6 * * 6")
+ self.assertRaises(ValueError, pycalc.calc, "(((((")
+ self.assertRaises(ValueError, pycalc.calc, "pow(2, 3, 4)")