SupyML: Add nesting control

master
Valentin Lorentz 2010-11-14 15:06:17 +01:00
parent 4a7d2ec9ef
commit 078bc676ae
3 changed files with 30 additions and 4 deletions

View File

@ -55,5 +55,7 @@ SupyML = conf.registerPlugin('SupyML')
# conf.registerGlobalValue(SupyML, 'someConfigVariableName', # conf.registerGlobalValue(SupyML, 'someConfigVariableName',
# registry.Boolean(False, _("""Help for someConfigVariableName."""))) # registry.Boolean(False, _("""Help for someConfigVariableName.""")))
conf.registerGlobalValue(SupyML, 'maxnodes', registry.Integer(30, """Determines
the maximum number of nodes processed by the 'SupyML eval' command."""))
# vim:set shiftwidth=4 tabstop=4 expandtab textwidth=79: # vim:set shiftwidth=4 tabstop=4 expandtab textwidth=79:

View File

@ -32,6 +32,7 @@ import re
import copy import copy
import time import time
import Queue import Queue
import supybot.conf as conf
from xml.dom import minidom from xml.dom import minidom
import supybot.world as world import supybot.world as world
import supybot.utils as utils import supybot.utils as utils
@ -60,6 +61,9 @@ class LoopError(Exception):
class LoopTypeIsMissing(Exception): class LoopTypeIsMissing(Exception):
pass pass
class MaximumNodesNumberExceeded(Exception):
pass
parseMessage = re.compile('\w+: (?P<content>.*)') parseMessage = re.compile('\w+: (?P<content>.*)')
class FakeIrc(): class FakeIrc():
def __init__(self, irc): def __init__(self, irc):
@ -87,19 +91,25 @@ class FakeIrc():
return getattr(self.__dict__['_irc'], name) return getattr(self.__dict__['_irc'], name)
class SupyMLParser: class SupyMLParser:
def __init__(self, plugin, irc, msg, code): def __init__(self, plugin, irc, msg, code, maxNodes):
self._plugin = plugin self._plugin = plugin
self._irc = irc self._irc = irc
self._msg = msg self._msg = msg
self._code = code self._code = code
self.warnings = [] self.warnings = []
self._maxNodes = maxNodes
self.nodesCount = 0
self.data = self._parse(code) self.data = self._parse(code)
def _startNode(self):
self.nodesCount += 1
if self.nodesCount >= self._maxNodes:
raise MaximumNodesNumberExceeded()
def _run(self, code): def _run(self, code):
"""Runs the command using Supybot engine""" """Runs the command using Supybot engine"""
tokens = callbacks.tokenize(str(code)) tokens = callbacks.tokenize(str(code))
fakeIrc = FakeIrc(self._irc) fakeIrc = FakeIrc(self._irc)
# TODO : add nested level
self._plugin.Proxy(fakeIrc, self._msg, tokens) self._plugin.Proxy(fakeIrc, self._msg, tokens)
self.rawData = fakeIrc._rawData self.rawData = fakeIrc._rawData
# TODO : don't wait if the plugin is not threaded # TODO : don't wait if the plugin is not threaded
@ -108,6 +118,7 @@ class SupyMLParser:
def _parse(self, code, variables={}): def _parse(self, code, variables={}):
"""Returns a dom object from the code.""" """Returns a dom object from the code."""
self._startNode()
dom = minidom.parseString(code) dom = minidom.parseString(code)
output = self._processDocument(dom, variables) output = self._processDocument(dom, variables)
return output return output
@ -126,6 +137,7 @@ class SupyMLParser:
return node.data return node.data
output = node.nodeName + ' ' output = node.nodeName + ' '
for childNode in node.childNodes: for childNode in node.childNodes:
self._startNode()
if not repr(node) == repr(childNode.parentNode): if not repr(node) == repr(childNode.parentNode):
continue continue
if childNode.nodeName == 'loop': if childNode.nodeName == 'loop':
@ -204,7 +216,8 @@ class SupyML(callbacks.Plugin):
"""<SupyML script> """<SupyML script>
Executes the <SupyML script>""" Executes the <SupyML script>"""
parser = SupyMLParser(self, irc, msg, code) parser = SupyMLParser(self, irc, msg, code,
self.registryValue('maxnodes')+2)
if world.testing and len(parser.warnings) != 0: if world.testing and len(parser.warnings) != 0:
print parser.warnings print parser.warnings
if parser.rawData is not None: if parser.rawData is not None:

View File

@ -36,7 +36,7 @@ class SupyMLTestCase(ChannelPluginTestCase):
################################# #################################
# Utilities # Utilities
def _getIfAnswerIsEqual(self, msg): def _getIfAnswerIsEqual(self, msg):
time.sleep(0.2) time.sleep(0.1)
m = self.irc.takeMsg() m = self.irc.takeMsg()
while m is not None: while m is not None:
if repr(m) == repr(msg): if repr(m) == repr(msg):
@ -137,5 +137,16 @@ class SupyMLTestCase(ChannelPluginTestCase):
'</echo>', '</echo>',
'45') '45')
def testMaxNesting(self):
self.assertNotError('SupyML eval ' +
'<echo>'*30+
'foo' +
'</echo>'*30
)
self.assertError('SupyML eval ' +
'<echo>'*31+
'foo' +
'</echo>'*31
)
# vim:set shiftwidth=4 tabstop=4 expandtab textwidth=79: # vim:set shiftwidth=4 tabstop=4 expandtab textwidth=79: