Merge lp:~stefanor/ibid/calc-336195 into lp:~ibid-core/ibid/old-trunk-pack-0.92

Proposed by Stefano Rivera
Status: Superseded
Proposed branch: lp:~stefanor/ibid/calc-336195
Merge into: lp:~ibid-core/ibid/old-trunk-pack-0.92
Diff against target: None lines
To merge this branch: bzr merge lp:~stefanor/ibid/calc-336195

This proposal supersedes a proposal from 2009-04-16.

This proposal has been superseded by a proposal from 2009-04-18.

To post a comment you must log in.
Revision history for this message
Stefano Rivera (stefanor) wrote : Posted in a previous version of this proposal

Rip it to shreds! (Or accept)

Revision history for this message
Stefano Rivera (stefanor) wrote :

Come on Vhata, don't be afraid

lp:~stefanor/ibid/calc-336195 updated
597. By Stefano Rivera

Use ast / compiler instead of expression munging

598. By Stefano Rivera

Comments

599. By Stefano Rivera

Timeout bc

Unmerged revisions

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'ibid/plugins/math.py'
2--- ibid/plugins/math.py 2009-03-11 11:49:44 +0000
3+++ ibid/plugins/math.py 2009-04-16 08:14:59 +0000
4@@ -1,3 +1,4 @@
5+import logging
6 import re
7 from subprocess import Popen, PIPE
8
9@@ -7,6 +8,7 @@
10 from ibid.utils import file_in_path, unicode_output
11
12 help = {}
13+log = logging.getLogger('math')
14
15 help['bc'] = u'Calculate mathematical expressions using bc'
16 class BC(Processor):
17@@ -42,13 +44,22 @@
18 raise Exception("BC Error: %s" % error)
19
20 help['calc'] = u'Returns the anwser to mathematical expressions'
21+class LimitException(Exception):
22+ pass
23+
24+def limited_pow(*args):
25+ for arg, limit in zip(args, (1e100, 200)):
26+ if isinstance(arg, int) and (arg > limit or arg < -limit):
27+ raise LimitException
28+ return pow(*args)
29+
30 class Calc(Processor):
31 u"""[calc] <expression>"""
32 feature = 'calc'
33
34 priority = 500
35
36- extras = ('abs', 'pow', 'round', 'min', 'max')
37+ extras = ('abs', 'round', 'min', 'max')
38 banned = ('for', 'yield', 'lambda')
39
40 # Create a safe dict to pass to eval() as locals
41@@ -57,6 +68,7 @@
42 del safe['__builtins__']
43 for function in extras:
44 safe[function] = eval(function)
45+ safe['pow'] = limited_pow
46
47 @match(r'^(?:calc\s+)?(.+?)$')
48 def calculate(self, event, expression):
49@@ -64,6 +76,44 @@
50 if term in expression:
51 return
52
53+ # Replace the power operator with our limited pow function
54+ # Due to its binding, we try to match from right to left, but respect brackets
55+ pow_re = re.compile(r'^(.*\)|(.*?)((?:[0-9.]+[eE]-?)?\d+))\s*\*\*\s*(\w*\(.*|[+-~]?\s*[0-9.]+(?:[eE]-?\d+)?)(.*?)$')
56+ func_re = re.compile(r'^(.*?[\s(])(\w+)$')
57+ while '**' in expression:
58+ brleft, prefix, left, right, suffix = pow_re.match(expression).groups()
59+ if left == None and prefix == None:
60+ left = brleft
61+ prefix = u''
62+
63+ if ')' in left:
64+ brackets = 0
65+ for pos, c in enumerate(reversed(left)):
66+ if c == ')':
67+ brackets += 1
68+ elif c == '(':
69+ brackets -= 1
70+ if brackets == 0:
71+ prefix, left = prefix + left[:-pos - 1], left[-pos - 1:]
72+ # The open bracket may have been preceeded by a function name
73+ m = func_re.match(prefix)
74+ if m:
75+ prefix, left = m.group(1), m.group(2) + left
76+
77+ if '(' in right:
78+ brackets = 0
79+ for pos, c in enumerate(right):
80+ if c == '(':
81+ brackets += 1
82+ elif c == ')':
83+ brackets -= 1
84+ if brackets == 0:
85+ right, suffix = right[:pos + 1], right[pos + 1:]
86+
87+ expression = u'%s pow(%s, %s) %s' % (prefix, left, right, suffix)
88+
89+ #log.debug('Normalised expression to %s', expression)
90+
91 try:
92 result = eval(expression, {'__builtins__': None}, self.safe)
93 except ZeroDivisionError, e:
94@@ -76,6 +126,9 @@
95 if unicode(e) == u"math domain error":
96 event.addresponse(u"I can't do that: %s", unicode(e))
97 return
98+ except LimitException, e:
99+ event.addresponse(u"I'm afraid I'm not allowed to play with big numbers")
100+ return
101 except Exception, e:
102 return
103

Subscribers

People subscribed via source and target branches