diff --git a/plugins/Math/plugin.py b/plugins/Math/plugin.py index 81c2ff3eb..21250aacc 100644 --- a/plugins/Math/plugin.py +++ b/plugins/Math/plugin.py @@ -166,8 +166,8 @@ class Math(callbacks.Plugin): """ try: self.log.info('evaluating %q from %s', text, msg.prefix) - x = safe_eval(text, allow_ints=True) - irc.reply(str(x)) + result = safe_eval(text, allow_ints=True) + float(result) # fail early if it is too large to be displayed except OverflowError: maxFloat = math.ldexp(0.9999999999999999, 1024) irc.error(_('The answer exceeded %s or so.') % maxFloat) @@ -177,6 +177,17 @@ class Math(callbacks.Plugin): irc.error(_('%s is not a defined function.') % str(e).split()[1]) except Exception as e: irc.error(utils.exnToString(e)) + else: + try: + result_str = str(result) + except ValueError as e: + # Probably too large to be converted to string; go through + # floats instead. + # https://docs.python.org/3/library/stdtypes.html#int-max-str-digits + # (Depending on configuration, this may be dead code because it + # is caught by the float() check above. + result_str = str(float(result)) + irc.reply(result_str) icalc = wrap(icalc, [('checkCapability', 'trusted'), 'text']) _rpnEnv = { diff --git a/plugins/Math/test.py b/plugins/Math/test.py index d33aff396..22578c9ed 100644 --- a/plugins/Math/test.py +++ b/plugins/Math/test.py @@ -112,7 +112,10 @@ class MathTestCase(PluginTestCase): self.assertNotError('calc (1600 * 1200) - 2*(1024*1280)') self.assertNotError('calc 3-2*4') self.assertNotError('calc (1600 * 1200)-2*(1024*1280)') - self.assertError('calc factorial(20000)') + self.assertResponse('calc factorial(20000)', + 'Error: factorial argument too large') + self.assertResponse('calc factorial(20000) / factorial(19999)', + 'Error: factorial argument too large') def testCalcNoNameError(self): self.assertRegexp('calc foobar(x)', 'foobar is not a defined function') @@ -147,7 +150,10 @@ class MathTestCase(PluginTestCase): self.assertResponse('icalc 1^1', '0') self.assertResponse('icalc 10**24', '1' + '0'*24) self.assertRegexp('icalc 49/6', '8.16') - self.assertNotError('icalc factorial(20000)') + self.assertRegexp('icalc factorial(20000)', + 'Error: The answer exceeded') + self.assertResponse('icalc factorial(20000) / factorial(19999)', + '20000.0') def testRpn(self): self.assertResponse('rpn 5 2 +', '7')