jaraco / irc

Full-featured Python IRC library for Python.
MIT License
392 stars 86 forks source link

[Python 3.3] TypeError with buffer_class = irc.buffer.LineBuffer #37

Closed jaraco closed 8 years ago

jaraco commented 8 years ago

Hi,

With python 3.3, when using irc.client.ServerConnection.buffer_class = irc.buffer.LineBuffer, I get the following traceback:

Traceback (most recent call last):
  File "testbot.py", line 120, in <module>
    main()
  File "testbot.py", line 117, in main
    bot.start()
  File "/usr/pkg/lib/python3.3/site-packages/irc/bot.py", line 266, in start
    super(SingleServerIRCBot, self).start()
  File "/usr/pkg/lib/python3.3/site-packages/irc/client.py", line 1225, in start
    self.ircobj.process_forever()
  File "/usr/pkg/lib/python3.3/site-packages/irc/client.py", line 267, in process_forever
    self.process_once(timeout)
  File "/usr/pkg/lib/python3.3/site-packages/irc/client.py", line 248, in process_once
    self.process_data(i)
  File "/usr/pkg/lib/python3.3/site-packages/irc/client.py", line 213, in process_data
    c.process_data()
  File "/usr/pkg/lib/python3.3/site-packages/irc/client.py", line 561, in process_data
    self._process_line(line)
  File "/usr/pkg/lib/python3.3/site-packages/irc/client.py", line 572, in _process_line
    m = _rfc_1459_command_regexp.match(line)
TypeError: can't use a string pattern on a bytes-like object

This is the testbot.py code with the following added before irc.bot.SingleServerIRCBot: irc.client.ServerConnection.buffer_class = irc.buffer.LineBuffer This works with python 2.7.


jaraco commented 8 years ago

This issue is due to the assumption by the ServerConnection that the 'line' passed to _process_line is text (not bytes). Python 2 will magically transform these values into strings, but Python 3 will not.

It is for this reason that the default behavior is to use the DecodingLineBuffer, which works on Python 3. Not only does the command regular expression expect strings. So also does the checks for different command types, which compare commands to other strings. Byte strings will not match:

>>> b'foo' == "foo"
False

What is the solution to this? I'm not yet sure. I'm tempted to say that byte strings are not supported in Python 3, even though I know some clients depend on this behavior.

I suspect the alternative is to allow customization of the dispatcher (process_line method) so that clients can supply a dispatcher for byte strings.

Can you tell me more about your use-case? Is it possible you could use a DecodingLineBuffer (perhaps with errors='replace' or using a more lenient decoding scheme)?


Original comment by: Jason R. Coombs

jaraco commented 8 years ago

After further consideration, I believe the IRC library does not want to support handling of raw bytes. The LineBuffer is now deprecated in favor of the LenientDecodingLineBuffer. Python 3 users should use the LenientDecodingLineBuffer or the 'latin-1' encoding for the DecodingLineBuffer. Fixes #37.

→ <<cset 5eae3e731cd2>>


Original comment by: Jason R. Coombs