Merge lp:~stefanor/ibid/calc-525439 into lp:~ibid-core/ibid/old-trunk-1.6

Proposed by Stefano Rivera
Status: Merged
Approved by: Jonathan Hitchcock
Approved revision: not available
Merged at revision: 900
Proposed branch: lp:~stefanor/ibid/calc-525439
Merge into: lp:~ibid-core/ibid/old-trunk-1.6
Diff against target: 86 lines (+23/-15)
2 files modified
ibid/plugins/__init__.py (+13/-12)
ibid/plugins/calc.py (+10/-3)
To merge this branch: bzr merge lp:~stefanor/ibid/calc-525439
Reviewer Review Type Date Requested Status
Jonathan Hitchcock Approve
Keegan Carruthers-Smith Approve
Michael Gorven Approve
Review via email: mp+19957@code.launchpad.net

This proposal supersedes a proposal from 2010-02-23.

To post a comment you must log in.
Revision history for this message
Michael Gorven (mgorven) wrote : Posted in a previous version of this proposal

 review approve

review: Approve
Revision history for this message
Michael Gorven (mgorven) wrote : Posted in a previous version of this proposal

Hackity hack...
 review approve

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

21:10 <@cocooncrash> tumbleweed: Er, I don't quite understand what you're doing in calc
21:11 < tumbleweed> ok, let me explain what I had to change

here goes:

Previously module authors could bypass the Processor inspection (to locate handler functions) by providing a class level list "_event_handlers" of handlers, otherwise it inspects and builds a list of the same name.

Problem with that is when you inherit from a Processor then the subclass assumes that the existing _event_handlers was manual, when it really comes from inspecting the base class.

Solution:
Store the inspected list in __event_handlers (which has to be manually mangled because setattr et al. don't mangle). And extend the list during subclass initialisation. Overriding with a manual list works as before.

Revision history for this message
Michael Gorven (mgorven) :
review: Approve
Revision history for this message
Keegan Carruthers-Smith (keegan-csmith) wrote :

Is _event_handlers or _periodic_handlers ever not None now?

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

> Is _event_handlers or _periodic_handlers ever not None now?

Nope. And _get_*_handlers isn't overridden by anyone either.

Revision history for this message
Keegan Carruthers-Smith (keegan-csmith) wrote :

Ok, I didn't see the comment explaining the code change when I commented. So a plugin can choose to manually override that.

I haven't really ever played with __new__ before, so I am not 100% what goes on with the setattr(). Say a subclass, A, of processor has _Processor__event_handlers as [handler_a]. Then B, a subclass of A, adds handler_b. So B._Processor__event_handlers is [handler_a, handler_b]? If so I am led to believe A. and Processor. _Processor__event_handlers is also [handler_a, handler_b]. Just wondering if this is intended and if this is how it works?

Also, maybe _Processor__*_handlers should be sets instead of lists?

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

> I haven't really ever played with __new__ before, so I am not 100% what goes
> on with the setattr().

setattr(a, 'b', 'c') is the same as a.b = c
however, setattr doesn't know to do name mangling if you say setattr(a, '__b')

> Say a subclass, A, of processor has _Processor__event_handlers as [handler_a].
> Then B, a subclass of A, adds handler_b. So B._Processor__event_handlers is
> [handler_a, handler_b]?

Correct

> If so I am led to believe A. and Processor. _Processor__event_handlers is also
> [handler_a, handler_b]. Just wondering if this is intended and if this is how
> it works?

Ok, that bit I don't understand. Explain to me on IRC

> Also, maybe _Processor__*_handlers should be sets instead of lists?

No. Definable order could be handy.

Revision history for this message
Keegan Carruthers-Smith (keegan-csmith) :
review: Approve
Revision history for this message
Jonathan Hitchcock (vhata) :
review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'ibid/plugins/__init__.py'
2--- ibid/plugins/__init__.py 2010-02-03 15:04:43 +0000
3+++ ibid/plugins/__init__.py 2010-02-23 11:48:19 +0000
4@@ -62,16 +62,17 @@
5 new.default = getattr(cls, name)
6 setattr(cls, name, new)
7
8- if getattr(cls, '_event_handlers', None) is None:
9- cls._event_handlers = []
10- for name, item in cls.__dict__.iteritems():
11- if getattr(item, 'handler', False):
12- cls._event_handlers.append(name)
13- if getattr(cls, '_periodic_handlers', None) is None:
14- cls._periodic_handlers = []
15- for name, item in cls.__dict__.iteritems():
16- if getattr(item, 'periodic', False):
17- cls._periodic_handlers.append(name)
18+ for attr, listname in (
19+ ('handler', 'event'),
20+ ('periodic', 'periodic')):
21+ listname = '_Processor__%s_handlers' % listname
22+ if not hasattr(cls, listname):
23+ setattr(cls, listname, [])
24+ handlers = getattr(cls, listname)
25+
26+ for name, item in cls.__dict__.iteritems():
27+ if getattr(item, attr, False) and name not in handlers:
28+ handlers.append(name)
29
30 return super(Processor, cls).__new__(cls)
31
32@@ -127,12 +128,12 @@
33
34 def _get_event_handlers(self):
35 "Find all the handlers (regex matching and blind)"
36- for handler in self._event_handlers:
37+ for handler in self._event_handlers or self.__event_handlers:
38 yield getattr(self, handler)
39
40 def _get_periodic_handlers(self):
41 "Find all the periodic handlers"
42- for handler in self._periodic_handlers:
43+ for handler in self._periodic_handlers or self.__periodic_handlers:
44 yield getattr(self, handler)
45
46 def _run_periodic_handler(self, method, event):
47
48=== modified file 'ibid/plugins/calc.py'
49--- ibid/plugins/calc.py 2010-01-18 23:20:33 +0000
50+++ ibid/plugins/calc.py 2010-02-23 11:48:19 +0000
51@@ -2,10 +2,9 @@
52 # Released under terms of the MIT/X/Expat Licence. See COPYING for details.
53
54 from __future__ import division
55-from random import random, randint
56-
57 import logging
58 from os import kill
59+from random import random, randint
60 from signal import SIGTERM
61 from subprocess import Popen, PIPE
62 from time import time, sleep
63@@ -151,7 +150,7 @@
64 safe['pow'] = limited_pow
65 safe['factorial'] = limited_factorial
66
67- @match(r'^(?:calc\s+)?(.+?)$')
68+ @match(r'^(.+)$')
69 def calculate(self, event, expression):
70 for term in self.banned:
71 if term in expression:
72@@ -193,6 +192,14 @@
73 if isinstance(result, (int, long, float, complex)):
74 event.addresponse(unicode(result))
75
76+
77+class ExplicitCalc(Calc):
78+ priority = 0
79+
80+ @match(r'^calc(?:ulate)?\s+(.+)$')
81+ def calculate(self, event, expression):
82+ super(ExplicitCalc, self).calculate(event, expression)
83+
84 help['random'] = u'Generates random numbers.'
85 class Random(Processor):
86 u"""random [ <max> | <min> <max> ]"""

Subscribers

People subscribed via source and target branches