Ticket #5329: issue5329-2.diff

File issue5329-2.diff, 19.8 KB (added by Ezio Melotti, 8 years ago)
  • twisted/words/test/test_irc.py

     
    16351635        self.assertEqual(self.f.getvalue(), s)
    16361636
    16371637
     1638    def test_sendMessage(self):
     1639        """
     1640        Sanity check for L{IRC.sendMessage}.
     1641        """
     1642        self.p.sendMessage('CMD', 'param1', 'param2')
     1643        self.assertEqual(self.f.getvalue(), 'CMD param1 param2\r\n')
     1644
     1645
    16381646    def testPrivmsg(self):
    16391647        self.p.privmsg("this-is-sender", "this-is-recip", "this is message")
    16401648        self.check(":this-is-sender PRIVMSG this-is-recip :this is message\r\n")
     
    21992207
    22002208
    22012209
     2210class CollectorClient(irc.IRCClient):
     2211    """
     2212    A client that saves in a list the names of the methods that got called.
     2213    """
     2214    def __init__(self, methods_list):
     2215        # methods_list is a list of methods' names that should be replaced
     2216        self.methods = []
     2217        self.nickname = 'Wolf'  # set 'Wolf' as the current nickname
     2218
     2219        for method in methods_list:
     2220            def fake_method(method=method):
     2221                def inner(*args):
     2222                    self.methods.append((method, args))
     2223                return inner
     2224            setattr(self, method, fake_method())
     2225
     2226
     2227
     2228class TestServerToClient(TestCase):
     2229    """
     2230    Tests for the irc_* methods sent from the server to the client.
     2231    """
     2232    def setUp(self):
     2233        methods_list = ['joined', 'userJoined', 'left', 'userLeft', 'userQuit',
     2234                        'noticed', 'kickedFrom', 'userKicked', 'topicUpdated']
     2235        self.client = CollectorClient(methods_list)
     2236
     2237
     2238    def test_irc_JOIN(self):
     2239        """
     2240        L{IRCClient.joined} is called when I join a channel;
     2241        l{IRCClient.userJoined} is called when someone else joins.
     2242        """
     2243        self.client.irc_JOIN('Wolf!~wolf@yok.utu.fi', ['#twisted'])
     2244        self.client.irc_JOIN('Svadilfari!~svadi@yok.utu.fi', ['#python'])
     2245        self.assertEqual(self.client.methods,
     2246                         [('joined', ('#twisted',)),
     2247                          ('userJoined', ('Svadilfari', '#python'))])
     2248
     2249
     2250    def test_irc_PART(self):
     2251        """
     2252        L{IRCClient.left} is called when I part the channel;
     2253        l{IRCClient.userLeft} is called when someone else parts.
     2254        """
     2255        self.client.irc_PART('Wolf!~wolf@yok.utu.fi', ['#twisted'])
     2256        self.client.irc_PART('Svadilfari!~svadi@yok.utu.fi', ['#python'])
     2257        self.assertEqual(self.client.methods,
     2258                         [('left', ('#twisted',)),
     2259                          ('userLeft', ('Svadilfari', '#python'))])
     2260
     2261
     2262    def test_irc_QUIT(self):
     2263        """
     2264        L{IRCClient.userQuit} is called whenever someone quits
     2265        the channel (myself included).
     2266        """
     2267        self.client.irc_QUIT('Svadilfari!~svadi@yok.utu.fi', ['Adios.'])
     2268        self.client.irc_QUIT('Wolf!~wolf@yok.utu.fi', ['Farewell.'])
     2269        self.assertEqual(self.client.methods,
     2270                         [('userQuit', ('Svadilfari', 'Adios.')),
     2271                          ('userQuit', ('Wolf', 'Farewell.'))])
     2272
     2273
     2274    def test_irc_NOTICE(self):
     2275        """
     2276        L{IRCClient.noticed} is called when a notice is received.
     2277        """
     2278        user = 'Wolf!~wolf@yok.utu.fi'
     2279        msg = ('%(X)cextended%(X)cdata1%(X)cextended%(X)cdata2%(X)c%(EOL)s' %
     2280               {'X': irc.X_DELIM, 'EOL': irc.CR + irc.LF})
     2281        self.client.irc_NOTICE(user, ['#twisted', msg])
     2282        self.assertEqual(self.client.methods,
     2283                         [('noticed', (user, '#twisted', 'data1 data2'))])
     2284
     2285
     2286    def test_irc_KICK(self):
     2287        """
     2288        L{IRCClient.kickedFrom} is called when I get kicked from the channel;
     2289        l{IRCClient.userKicked} is called when someone else gets kicked.
     2290        """
     2291        # fight!
     2292        self.client.irc_KICK('Svadilfari!~svadi@yok.utu.fi',
     2293                             ['#python', 'WOLF', 'shoryuken!'])
     2294        self.client.irc_KICK('Wolf!~wolf@yok.utu.fi',
     2295                             ['#twisted', 'Svadilfari', 'hadouken!'])
     2296        self.assertEqual(self.client.methods,
     2297                         [('kickedFrom',
     2298                           ('#python', 'Svadilfari', 'shoryuken!')),
     2299                          ('userKicked',
     2300                           ('Svadilfari', '#twisted', 'Wolf', 'hadouken!'))])
     2301
     2302
     2303    def test_irc_TOPIC(self):
     2304        """
     2305        L{IRCClient.topicUpdated} is called when someone sets the topic.
     2306        """
     2307        self.client.irc_TOPIC('Wolf!~wolf@yok.utu.fi',
     2308                              ['#twisted', 'new topic is new'])
     2309        self.assertEqual(self.client.methods,
     2310                         [('topicUpdated',
     2311                           ('Wolf', '#twisted', 'new topic is new'))])
     2312
     2313
     2314    def test_irc_RPL_TOPIC(self):
     2315        """
     2316        L{IRCClient.topicUpdated} is called when the topic is initially
     2317        reported.
     2318        """
     2319        self.client.irc_RPL_TOPIC('Wolf!~wolf@yok.utu.fi',
     2320                              ['?', '#twisted', 'new topic is new'])
     2321        self.assertEqual(self.client.methods,
     2322                         [('topicUpdated',
     2323                           ('Wolf', '#twisted', 'new topic is new'))])
     2324
     2325
     2326    def test_irc_RPL_NOTOPIC(self):
     2327        """
     2328        L{IRCClient.topicUpdated} is called when the topic is removed.
     2329        """
     2330        self.client.irc_RPL_NOTOPIC('Wolf!~wolf@yok.utu.fi', ['?', '#twisted'])
     2331        self.assertEqual(self.client.methods,
     2332                         [('topicUpdated', ('Wolf', '#twisted', ''))])
     2333
     2334
     2335
     2336class TestCTCPQuery(TestCase):
     2337    """
     2338    Tests for the ctcpQuery_* methods.
     2339    """
     2340    def setUp(self):
     2341        self.client = CollectorClient(['ctcpMakeReply'])
     2342
     2343
     2344    def test_ctcpQuery_PING(self):
     2345        """
     2346        Test that L{IRCClient.ctcpQuery_PING} calls L{IRCClient.ctcpMakeReply}
     2347        with the correct args.
     2348        """
     2349        self.client.ctcpQuery_PING('Wolf!~wolf@yok.utu.fi', '#twisted', 'data')
     2350        self.assertEqual(self.client.methods,
     2351                         [('ctcpMakeReply', ('Wolf', [('PING', 'data')]))])
     2352
     2353
     2354    def test_ctcpQuery_FINGER(self):
     2355        """
     2356        Test that L{IRCClient.ctcpQuery_FINGER} calls L{IRCClient.ctcpMakeReply}
     2357        with the correct args.
     2358        """
     2359        self.client.fingerReply = 'reply'
     2360        self.client.ctcpQuery_FINGER('Wolf!~wolf@yok.utu.fi',
     2361                                     '#twisted', 'data')
     2362        self.assertEqual(self.client.methods,
     2363                         [('ctcpMakeReply', ('Wolf', [('FINGER', 'reply')]))])
     2364
     2365
     2366    def test_ctcpQuery_SOURCE(self):
     2367        """
     2368        Test that L{IRCClient.ctcpQuery_SOURCE} calls L{IRCClient.ctcpMakeReply}
     2369        with the correct args.
     2370        """
     2371        self.client.sourceURL = 'url'
     2372        self.client.ctcpQuery_SOURCE('Wolf!~wolf@yok.utu.fi',
     2373                                     '#twisted', 'data')
     2374        self.assertEqual(self.client.methods,
     2375                         [('ctcpMakeReply', ('Wolf', [('SOURCE', 'url'),
     2376                                                      ('SOURCE', None)]))])
     2377
     2378
     2379    def test_ctcpQuery_USERINFO(self):
     2380        """
     2381        Test that L{IRCClient.ctcpQuery_USERINFO} calls L{IRCClient.ctcpMakeReply}
     2382        with the correct args.
     2383        """
     2384        self.client.userinfo = 'info'
     2385        self.client.ctcpQuery_USERINFO('Wolf!~wolf@yok.utu.fi',
     2386                                       '#twisted', 'data')
     2387        self.assertEqual(self.client.methods,
     2388                         [('ctcpMakeReply', ('Wolf', [('USERINFO', 'info')]))])
     2389
     2390
     2391    def test_ctcpQuery_CLIENTINFO(self):
     2392        """
     2393        Test that L{IRCClient.ctcpQuery_CLIENTINFO} calls
     2394        L{IRCClient.ctcpMakeReply} with the correct args.
     2395        """
     2396        self.client.ctcpQuery_CLIENTINFO('Wolf!~wolf@yok.utu.fi',
     2397                                         '#twisted', '')
     2398        self.client.ctcpQuery_CLIENTINFO('Wolf!~wolf@yok.utu.fi',
     2399                                         '#twisted', 'PING PONG')
     2400        info = ('CLIENTINFO PING DCC SOURCE VERSION '
     2401                'USERINFO TIME ACTION ERRMSG FINGER')
     2402        self.assertEqual(self.client.methods,
     2403                         [('ctcpMakeReply', ('Wolf', [('CLIENTINFO', info)])),
     2404                          ('ctcpMakeReply', ('Wolf', [('CLIENTINFO', None)]))])
     2405
     2406
     2407    def test_ctcpQuery_TIME(self):
     2408        """
     2409        Test that L{IRCClient.ctcpQuery_TIME} calls L{IRCClient.ctcpMakeReply}
     2410        with the correct args.
     2411        """
     2412        self.client.ctcpQuery_TIME('Wolf!~wolf@yok.utu.fi', '#twisted', 'data')
     2413        self.assertEqual(self.client.methods[0][1][0], 'Wolf')
     2414
     2415
     2416    def test_ctcpQuery_DCC(self):
     2417        """
     2418        Test that L{IRCClient.ctcpQuery_DCC} calls L{IRCClient.ctcpMakeReply}
     2419        with the correct args.
     2420        """
     2421        self.client.ctcpQuery_DCC('Wolf!~wolf@yok.utu.fi', '#twisted', 'data')
     2422        self.assertEqual(self.client.methods,
     2423                         [('ctcpMakeReply',
     2424                           ('Wolf', [('ERRMSG',
     2425                                      "DCC data :Unknown DCC type 'DATA'")]))])
     2426
     2427
     2428
    22022429class DccChatFactoryTests(unittest.TestCase):
    22032430    """
    22042431    Tests for L{DccChatFactory}
     
    22132440        p = f.buildProtocol('127.0.0.1')
    22142441        self.assertTrue(isinstance(p, irc.DccChat))
    22152442        self.assertEqual(p.factory, f)
     2443
     2444
     2445
     2446class dccDescribeTests(unittest.TestCase):
     2447    """
     2448    Tests for L{dccDescribe}
     2449    """
     2450    def test_address(self):
     2451        """
     2452        Test that long IP addresses are supported.
     2453        """
     2454        result = irc.dccDescribe('CHAT arg 3232235522 6666')
     2455        self.assertEqual(result, "CHAT for host 192.168.0.2, port 6666")
  • twisted/words/protocols/irc.py

     
    4545from twisted.persisted import styles
    4646from twisted.protocols import basic
    4747from twisted.python import log, reflect, text, _textattributes
     48from twisted.python.failure import Failure
    4849
    4950NUL = chr(0)
    5051CR = chr(015)
     
    276277            raise ValueError, "Somebody screwed up, 'cuz this doesn't" \
    277278                  " look like a command to me: %s" % command
    278279
    279         line = string.join([command] + list(parameter_list))
     280        line = ' '.join([command] + list(parameter_list))
    280281        if 'prefix' in prefix:
    281282            line = ":%s %s" % (prefix['prefix'], line)
    282283        self.sendLine(line)
     
    17681769        if not (size is None):
    17691770            args.append(size)
    17701771
    1771         args = string.join(args, ' ')
     1772        args = ' '.join(args)
    17721773
    17731774        self.ctcpMakeQuery(user, [('DCC', args)])
    17741775
     
    18521853        """
    18531854        Called when a user joins a channel.
    18541855        """
    1855         nick = string.split(prefix,'!')[0]
     1856        nick = prefix.split('!')[0]
    18561857        channel = params[-1]
    18571858        if nick == self.nickname:
    18581859            self.joined(channel)
     
    18631864        """
    18641865        Called when a user leaves a channel.
    18651866        """
    1866         nick = string.split(prefix,'!')[0]
     1867        nick = prefix.split('!')[0]
    18671868        channel = params[0]
    18681869        if nick == self.nickname:
    18691870            self.left(channel)
     
    18741875        """
    18751876        Called when a user has quit.
    18761877        """
    1877         nick = string.split(prefix,'!')[0]
     1878        nick = prefix.split('!')[0]
    18781879        self.userQuit(nick, params[0])
    18791880
    18801881
     
    19351936            if not m['normal']:
    19361937                return
    19371938
    1938             message = string.join(m['normal'], ' ')
     1939            message = ' '.join(m['normal'])
    19391940
    19401941        self.privmsg(user, channel, message)
    19411942
     
    19551956            if not m['normal']:
    19561957                return
    19571958
    1958             message = string.join(m['normal'], ' ')
     1959            message = ' '.join(m['normal'])
    19591960
    19601961        self.noticed(user, channel, message)
    19611962
     
    19631964        """
    19641965        Called when a user changes their nickname.
    19651966        """
    1966         nick = string.split(prefix,'!', 1)[0]
     1967        nick = prefix.split('!', 1)[0]
    19671968        if nick == self.nickname:
    19681969            self.nickChanged(params[0])
    19691970        else:
     
    19731974        """
    19741975        Called when a user is kicked from a channel.
    19751976        """
    1976         kicker = string.split(prefix,'!')[0]
     1977        kicker = prefix.split('!')[0]
    19771978        channel = params[0]
    19781979        kicked = params[1]
    19791980        message = params[-1]
    1980         if string.lower(kicked) == string.lower(self.nickname):
     1981        if kicked.lower() == self.nickname.lower():
    19811982            # Yikes!
    19821983            self.kickedFrom(channel, kicker, message)
    19831984        else:
     
    19871988        """
    19881989        Someone in the channel set the topic.
    19891990        """
    1990         user = string.split(prefix, '!')[0]
     1991        user = prefix.split('!')[0]
    19911992        channel = params[0]
    19921993        newtopic = params[1]
    19931994        self.topicUpdated(user, channel, newtopic)
     
    19971998        Called when the topic for a channel is initially reported or when it
    19981999        subsequently changes.
    19992000        """
    2000         user = string.split(prefix, '!')[0]
     2001        user = prefix.split('!')[0]
    20012002        channel = params[1]
    20022003        newtopic = params[2]
    20032004        self.topicUpdated(user, channel, newtopic)
    20042005
    20052006    def irc_RPL_NOTOPIC(self, prefix, params):
    2006         user = string.split(prefix, '!')[0]
     2007        user = prefix.split('!')[0]
    20072008        channel = params[1]
    20082009        newtopic = ""
    20092010        self.topicUpdated(user, channel, newtopic)
     
    21122113        self.action(user, channel, data)
    21132114
    21142115    def ctcpQuery_PING(self, user, channel, data):
    2115         nick = string.split(user,"!")[0]
     2116        nick = user.split('!')[0]
    21162117        self.ctcpMakeReply(nick, [("PING", data)])
    21172118
    21182119    def ctcpQuery_FINGER(self, user, channel, data):
     
    21272128        else:
    21282129            reply = str(self.fingerReply)
    21292130
    2130         nick = string.split(user,"!")[0]
     2131        nick = user.split('!')[0]
    21312132        self.ctcpMakeReply(nick, [('FINGER', reply)])
    21322133
    21332134    def ctcpQuery_VERSION(self, user, channel, data):
     
    21362137                               % (user, data))
    21372138
    21382139        if self.versionName:
    2139             nick = string.split(user,"!")[0]
     2140            nick = user.split('!')[0]
    21402141            self.ctcpMakeReply(nick, [('VERSION', '%s:%s:%s' %
    21412142                                       (self.versionName,
    21422143                                        self.versionNum or '',
     
    21472148            self.quirkyMessage("Why did %s send '%s' with a SOURCE query?"
    21482149                               % (user, data))
    21492150        if self.sourceURL:
    2150             nick = string.split(user,"!")[0]
     2151            nick = user.split('!')[0]
    21512152            # The CTCP document (Zeuge, Rollo, Mesander 1994) says that SOURCE
    21522153            # replies should be responded to with the location of an anonymous
    21532154            # FTP server in host:directory:file format.  I'm taking the liberty
     
    21602161            self.quirkyMessage("Why did %s send '%s' with a USERINFO query?"
    21612162                               % (user, data))
    21622163        if self.userinfo:
    2163             nick = string.split(user,"!")[0]
     2164            nick = user.split('!')[0]
    21642165            self.ctcpMakeReply(nick, [('USERINFO', self.userinfo)])
    21652166
    21662167    def ctcpQuery_CLIENTINFO(self, user, channel, data):
     
    21722173        the usage of that tag.
    21732174        """
    21742175
    2175         nick = string.split(user,"!")[0]
     2176        nick = user.split('!')[0]
    21762177        if not data:
    21772178            # XXX: prefixedMethodNames gets methods from my *class*,
    21782179            # but it's entirely possible that this *instance* has more
     
    21802181            names = reflect.prefixedMethodNames(self.__class__,
    21812182                                                'ctcpQuery_')
    21822183
    2183             self.ctcpMakeReply(nick, [('CLIENTINFO',
    2184                                        string.join(names, ' '))])
     2184            self.ctcpMakeReply(nick, [('CLIENTINFO', ' '.join(names))])
    21852185        else:
    2186             args = string.split(data)
     2186            args = data.split()
    21872187            method = getattr(self, 'ctcpQuery_%s' % (args[0],), None)
    21882188            if not method:
    21892189                self.ctcpMakeReply(nick, [('ERRMSG',
     
    21982198    def ctcpQuery_ERRMSG(self, user, channel, data):
    21992199        # Yeah, this seems strange, but that's what the spec says to do
    22002200        # when faced with an ERRMSG query (not a reply).
    2201         nick = string.split(user,"!")[0]
     2201        nick = user.split('!')[0]
    22022202        self.ctcpMakeReply(nick, [('ERRMSG',
    22032203                                   "%s :No error has occoured." % data)])
    22042204
     
    22062206        if data is not None:
    22072207            self.quirkyMessage("Why did %s send '%s' with a TIME query?"
    22082208                               % (user, data))
    2209         nick = string.split(user,"!")[0]
     2209        nick = user.split('!')[0]
    22102210        self.ctcpMakeReply(nick,
    22112211                           [('TIME', ':%s' %
    22122212                             time.asctime(time.localtime(time.time())))])
     
    22242224            data = data[len(dcctype)+1:]
    22252225            handler(user, channel, data)
    22262226        else:
    2227             nick = string.split(user,"!")[0]
     2227            nick = user.split('!')[0]
    22282228            self.ctcpMakeReply(nick, [('ERRMSG',
    22292229                                       "DCC %s :Unknown DCC type '%s'"
    22302230                                       % (data, dcctype))])
     
    23932393    def badMessage(self, line, excType, excValue, tb):
    23942394        """When I get a message that's so broken I can't use it.
    23952395        """
    2396         log.msg(line)
    2397         log.msg(string.join(traceback.format_exception(excType,
    2398                                                         excValue,
    2399                                                         tb),''))
     2396        log.err(Failure(excValue, excType, tb),
     2397                'bad message received: %r', (line,))
    24002398
    24012399    def quirkyMessage(self, s):
    24022400        """This is called when I receive a message which is peculiar,
     
    26612659
    26622660    def dataReceived(self, data):
    26632661        self.buffer = self.buffer + data
    2664         lines = string.split(self.buffer, LF)
     2662        lines = self.buffer.split(LF)
    26652663        # Put the (possibly empty) element after the last LF back in the
    26662664        # buffer
    26672665        self.buffer = lines.pop()
     
    27032701    """
    27042702
    27052703    orig_data = data
    2706     data = string.split(data)
     2704    data = data.split()
    27072705    if len(data) < 4:
    27082706        return orig_data
    27092707
     
    27252723                )
    27262724            # The mapping to 'int' is to get rid of those accursed
    27272725            # "L"s which python 1.5.2 puts on the end of longs.
    2728             address = string.join(map(str,map(int,address)), ".")
     2726            address = '.'.join(map(str, address))
    27292727
    27302728    if dcctype == 'SEND':
    27312729        filename = arg
     
    33353333    retval = {'extended': extended_messages,
    33363334              'normal': normal_messages }
    33373335
    3338     messages = string.split(message, X_DELIM)
     3336    messages = message.split(X_DELIM)
    33393337    odd = 0
    33403338
    33413339    # X1 extended data X2 nomal data X3 extended data X4 normal...
     
    33513349
    33523350    extended_messages[:] = map(ctcpDequote, extended_messages)
    33533351    for i in xrange(len(extended_messages)):
    3354         m = string.split(extended_messages[i], SPC, 1)
     3352        m = extended_messages[i].split(SPC, 1)
    33553353        tag = m[0]
    33563354        if len(m) > 1:
    33573355            data = m[1]
     
    33823380
    33833381def lowQuote(s):
    33843382    for c in (M_QUOTE, NUL, NL, CR):
    3385         s = string.replace(s, c, mQuoteTable[c])
     3383        s = s.replace(c, mQuoteTable[c])
    33863384    return s
    33873385
    33883386def lowDequote(s):
     
    34123410
    34133411def ctcpQuote(s):
    34143412    for c in (X_QUOTE, X_DELIM):
    3415         s = string.replace(s, c, xQuoteTable[c])
     3413        s = s.replace(c, xQuoteTable[c])
    34163414    return s
    34173415
    34183416def ctcpDequote(s):
     
    34513449        m = "%s%s%s" % (X_DELIM, m, X_DELIM)
    34523450        coded_messages.append(m)
    34533451
    3454     line = string.join(coded_messages, '')
     3452    line = ''.join(coded_messages)
    34553453    return line
    34563454
    34573455