diff --git a/src/ircutils.py b/src/ircutils.py index fc71523b8..0f8f54363 100644 --- a/src/ircutils.py +++ b/src/ircutils.py @@ -79,8 +79,9 @@ def toLower(nick): def nickEqual(nick1, nick2): return toLower(nick1) == toLower(nick2) -nickchars = string.ascii_lowercase + string.ascii_uppercase + r'-[]\\`^{}' -_nickre = re.compile(r'^[%s]+$' % re.escape(nickchars)) +_nickchars = r'-[]\\`^{}' +_nickre = re.compile(r'^[%sA-Za-z][%s0-9A-Za-z]+$' % (re.escape(_nickchars), + re.escape(_nickchars))) def isNick(s): if re.match(_nickre, s): return True @@ -192,6 +193,7 @@ def replyTo(msg): else: return msg.nick + class nick(str): """This class does case-insensitive comparisons of nicks.""" def __init__(self, s): @@ -206,6 +208,16 @@ class nick(str): def __hash__(self): return hash(self.lowered) + +class IrcDict(dict): + def __contains__(self, s): + return dict.__contains__(self, toLower(s)) + def __setitem__(self, s, v): + dict.__setitem__(self, toLower(s), v) + def __getitem__(self, s): + return dict.__getitem__(self, toLower(s)) + has_key = __contains__ + if __name__ == '__main__': import sys, doctest doctest.testmod(sys.modules['__main__']) diff --git a/test/ircutils_test.py b/test/ircutils_test.py index 03d91d2b5..4c2ea7edf 100644 --- a/test/ircutils_test.py +++ b/test/ircutils_test.py @@ -81,6 +81,16 @@ class FunctionsTestCase(unittest.TestCase): self.failIf(ircutils.isIP('a.b.c')) self.failUnless(ircutils.isIP('100.100.100.100')) + def testIsNick(self): + self.failUnless(ircutils.isNick('jemfinch')) + self.failUnless(ircutils.isNick('jemfinch0')) + self.failUnless(ircutils.isNick('[0]')) + self.failUnless(ircutils.isNick('{jemfinch}')) + self.failUnless(ircutils.isNick('\\```')) + self.failIf(ircutils.isNick('')) + self.failIf(ircutils.isNick('8foo')) + self.failIf(ircutils.isNick('10')) + def banmask(self): for msg in msgs: if ircutils.isUserHostmask(msg.prefix): @@ -123,3 +133,19 @@ class FunctionsTestCase(unittest.TestCase): modes = [plusB, plusE, minusL] self.assertEqual(ircutils.joinModes(modes), ['+be-l', plusB[1], plusE[1]]) + + +class IrcDictTestCase(unittest.TestCase): + def testContains(self): + d = ircutils.IrcDict() + d['#FOO'] = None + self.failUnless('#foo' in d) + d['#fOOBAR[]'] = None + self.failUnless('#foobar{}' in d) + + def testGetSetItem(self): + d = ircutils.IrcDict() + d['#FOO'] = 12 + self.assertEqual(12, d['#foo']) + d['#fOOBAR[]'] = 'blah' + self.assertEqual('blah', d['#foobar{}'])