本文整理汇总了Python中asyncio.queues.Queue.put_nowait方法的典型用法代码示例。如果您正苦于以下问题:Python Queue.put_nowait方法的具体用法?Python Queue.put_nowait怎么用?Python Queue.put_nowait使用的例子?那么, 这里精选的方法代码示例或许可以为您提供帮助。您也可以进一步了解该方法所在类asyncio.queues.Queue
的用法示例。
在下文中一共展示了Queue.put_nowait方法的12个代码示例,这些例子默认根据受欢迎程度排序。您可以为喜欢或者感觉有用的代码点赞,您的评价将有助于系统推荐出更棒的Python代码示例。
示例1: IRCClientProtocol
# 需要导入模块: from asyncio.queues import Queue [as 别名]
# 或者: from asyncio.queues.Queue import put_nowait [as 别名]
class IRCClientProtocol(asyncio.Protocol):
"""Low-level protocol that speaks the client end of IRC.
This isn't responsible for very much besides the barest minimum definition
of an IRC client: connecting and responding to PING.
You probably want `read_message`, or the higher-level client class.
"""
def __init__(self, loop, nick, password, charset="utf8"):
self.nick = nick
self.password = password
self.charset = charset
self.buf = b""
self.message_queue = Queue(loop=loop)
self.registered = False
def connection_made(self, transport):
self.transport = transport
if self.password:
self.send_message("PASS", self.password)
self.send_message("NICK", self.nick)
self.send_message("USER", "dywypi", "-", "-", "dywypi Python IRC bot")
def data_received(self, data):
data = self.buf + data
while True:
raw_message, delim, data = data.partition(b"\r\n")
if not delim:
# Incomplete message; stop here and wait for more
self.buf = raw_message
return
# TODO valerr
message = IRCMessage.parse(raw_message.decode(self.charset))
logger.debug("recv: %r", message)
self.handle_message(message)
def handle_message(self, message):
if message.command == "PING":
self.send_message("PONG", message.args[-1])
elif message.command == "RPL_WELCOME":
# 001, first thing sent after registration
if not self.registered:
self.registered = True
self.message_queue.put_nowait(message)
def send_message(self, command, *args):
message = IRCMessage(command, *args)
logger.debug("sent: %r", message)
self.transport.write(message.render().encode(self.charset) + b"\r\n")
@asyncio.coroutine
def read_message(self):
return (yield from self.message_queue.get())
示例2: _serve
# 需要导入模块: from asyncio.queues import Queue [as 别名]
# 或者: from asyncio.queues.Queue import put_nowait [as 别名]
async def _serve(self, websocket, path):
import websockets
connection_id = await websocket.recv()
with self.queue_lock:
#if connection_id in self._preclosed_connections:
# self._preclosed_connections[connection_id].set()
# return
pmqueue = self._pending_message_queues.get(connection_id, None)
myqueue = Queue()
if pmqueue is not None:
events = []
while 1:
try:
e = pmqueue.get_nowait()
except QueueEmpty:
break
events.append(e)
if len(events) > self.CACHE_EVENTS_FIRST + self.CACHE_EVENTS_LAST:
events = events[:self.CACHE_EVENTS_FIRST] + \
events[-self.CACHE_EVENTS_LAST:]
for enr, e in enumerate(events):
swallow = False
if e.get("type", None) == "var":
varname = e.get("var", None)
if varname is not None:
for e2 in events[enr+1:]:
if e2.get("type", None) != "var":
continue
if e2.get("var", None) != varname:
continue
swallow = True
break
if swallow:
continue
myqueue.put_nowait(e)
pmqueue.put_nowait(e) #put the events back
if connection_id not in self._message_queue_lists:
self._message_queue_lists[connection_id] = []
self._message_queue_lists[connection_id].append(myqueue)
while True:
#print("WAIT")
try:
message = await myqueue.get()
except Exception:
break
message = json.dumps(message)
#print("SEND?", message)
if message is None: #terminating message
break
try:
#print("SEND", message)
await websocket.send(message)
except websockets.exceptions.ConnectionClosed:
break
with self.queue_lock:
self._message_queue_lists[connection_id].remove(myqueue)
示例3: Core
# 需要导入模块: from asyncio.queues import Queue [as 别名]
# 或者: from asyncio.queues.Queue import put_nowait [as 别名]
class Core(object):
def __init__(self, bot):
self.bot = bot
self.timeout = int(self.bot.config.get('timeout'))
self.ping_queue = Queue(loop=bot.loop)
def connection_made(self):
self.bot.loop.call_later(self.timeout, self.check_ping)
self.ping_queue.put_nowait(self.bot.loop.time())
def check_ping(self): # pragma: no cover
# check if we received a ping
# reconnect if queue is empty
self.bot.log.debug(
'Ping queue size: {}'.format(self.ping_queue.qsize()))
if self.ping_queue.empty():
self.bot.loop.call_soon(self.bot.protocol.transport.close)
else:
self.bot.loop.call_later(self.timeout, self.check_ping)
while not self.ping_queue.empty():
self.ping_queue.get_nowait()
@event(rfc.PING)
def pong(self, data):
"""PING reply"""
self.ping_queue.put_nowait(self.bot.loop.time())
self.bot.send('PONG ' + data)
@event(rfc.NEW_NICK)
def recompile(self, nick=None, new_nick=None, **kw):
"""recompile regexp on new nick"""
if self.bot.nick == nick.nick:
self.bot.config['nick'] = new_nick
self.bot.recompile()
@event(rfc.ERR_NICK)
def badnick(self, me=None, nick=None, **kw):
"""Use alt nick on nick error"""
if me == '*':
self.bot.set_nick(self.bot.nick + '_')
self.bot.log.debug('Trying to regain nickname in 30s...')
self.bot.loop.call_later(30, self.bot.set_nick, self.bot.original_nick)
@event(rfc.RPL_ENDOFMOTD)
def autojoin(self, **kw):
"""autojoin at the end of MOTD"""
self.bot.config['nick'] = kw['me']
self.bot.recompile()
channels = utils.as_list(self.bot.config.get('autojoins', []))
for channel in channels:
channel = utils.as_channel(channel)
self.bot.log.info('Trying to join %s', channel)
self.bot.join(channel)
示例4: IrcConnection
# 需要导入模块: from asyncio.queues import Queue [as 别名]
# 或者: from asyncio.queues.Queue import put_nowait [as 别名]
class IrcConnection(asyncio.Protocol):
"""asyncio protocol to handle an irc connection"""
def connection_made(self, transport):
self.transport = transport
self.closed = False
self.queue = Queue()
def data_received(self, data):
encoding = getattr(self, 'encoding', 'ascii')
data = data.decode(encoding, 'ignore')
if not self.queue.empty():
data = self.queue.get_nowait() + data
lines = data.split('\r\n')
self.queue.put_nowait(lines.pop(-1))
for line in lines:
self.factory.dispatch(line)
def write(self, data):
if data is not None:
if isinstance(data, text_type):
data = data.encode(self.encoding)
if not data.endswith(b'\r\n'):
data = data + b'\r\n'
self.transport.write(data)
def connection_lost(self, exc): # pragma: no cover
self.factory.log.critical('connection lost (%s): %r',
id(self.transport),
exc)
self.factory.notify('connection_lost')
if not self.closed:
self.close()
# wait a few before reconnect
self.factory.loop.call_later(
2, self.factory.create_connection, self.__class__)
def close(self): # pragma: no cover
if not self.closed:
self.factory.log.critical('closing old transport (%r)',
id(self.transport))
try:
self.transport.close()
finally:
self.closed = True
示例5: HttpProtocol
# 需要导入模块: from asyncio.queues import Queue [as 别名]
# 或者: from asyncio.queues.Queue import put_nowait [as 别名]
class HttpProtocol(asyncio.Protocol):
def __init__(self, loop, handler):
self.parser = cparser.HttpRequestParser(
self.on_headers, self.on_body, self.on_error)
self.loop = loop
self.response = Response()
if flavor == 'queue':
def connection_made(self, transport):
self.transport = transport
self.queue = Queue(loop=self.loop)
self.loop.create_task(handle_requests(self.queue, transport))
else:
def connection_made(self, transport):
self.transport = transport
def connection_lost(self, exc):
self.parser.feed_disconnect()
def data_received(self, data):
self.parser.feed(data)
def on_headers(self, request):
return
if flavor == 'block':
def on_body(self, request):
handle_request_block(request, self.transport, self.response)
elif flavor == 'dump':
def on_body(self, request):
handle_dump(request, self.transport, self.response)
elif flavor == 'task':
def on_body(self, request):
self.loop.create_task(handle_request(request, self.transport))
elif flavor == 'queue':
def on_body(self, request):
self.queue.put_nowait(request)
elif flavor == 'inline':
def on_body(self, request):
body = 'Hello inlin!'
status_code = 200
mime_type = 'text/plain'
encoding = 'utf-8'
text = [b'HTTP/1.1 ']
text.extend([str(status_code).encode(), b' OK\r\n'])
text.append(b'Connection: keep-alive\r\n')
text.append(b'Content-Length: ')
text.extend([str(len(body)).encode(), b'\r\n'])
text.extend([
b'Content-Type: ', mime_type.encode(),
b'; encoding=', encoding.encode(), b'\r\n\r\n'])
text.append(body.encode())
self.transport.write(b''.join(text))
elif flavor == 'static':
def on_body(self, request):
self.transport.write(static_response)
def on_error(self, error):
print(error)
示例6: events
# 需要导入模块: from asyncio.queues import Queue [as 别名]
# 或者: from asyncio.queues.Queue import put_nowait [as 别名]
#.........这里部分代码省略.........
# TODO we should probably not ever have a names future AND a
# pending join at the same time. or, does it matter?
self._names_futures[channel_name].set_result(namelist)
del self._names_futures[channel_name]
if channel_name in self.joined_channels:
# Join synchronized!
channel = self.joined_channels[channel_name]
channel.sync = True
channel.topic = self._pending_topics.pop(channel_name, None)
for name in namelist:
modes = set()
# TODO use features!
while name and name[0] in '+%@&~':
modes.add(name[0])
name = name[1:]
# TODO haha no this is so bad.
# TODO the bot should, obviously, keep a record of all
# known users as well. alas, mutable everything.
peer = Peer(name, None, None)
channel.add_user(peer, modes)
if channel_name in self._join_futures:
# Update the Future
self._join_futures[channel_name].set_result(channel)
del self._join_futures[channel_name]
def _handle_PRIVMSG(self, message):
event = Message(self, message)
self.event_queue.put_nowait(event)
@asyncio.coroutine
def read_event(self):
"""Produce a single IRC event.
This client does not do any kind of multiplexing or event handler
notification; that's left to a higher level.
"""
return (yield from self.event_queue.get())
# Implementations of particular commands
# TODO should this be part of the general client interface, or should there
# be a separate thing that smooths out the details?
@asyncio.coroutine
def say(self, target, message):
"""Coroutine that sends a message to a target, which may be either a
`Channel` or a `Peer`.
"""
yield from self.send_message('PRIVMSG', target, message)
def join(self, channel_name, key=None):
"""Coroutine that joins a channel, and nonblocks until the join is
"synchronized" (defined as receiving the nick list).
"""
if channel_name in self._join_futures:
return self._join_futures[channel_name]
# TODO multiple? error on commas?
if key is None:
self.proto.send_message('JOIN', channel_name)
示例7: __init__
# 需要导入模块: from asyncio.queues import Queue [as 别名]
# 或者: from asyncio.queues.Queue import put_nowait [as 别名]
class DCCClient:
def __init__(self, loop, network, send=False):
self.loop = loop
self.network = network
self.read_queue = Queue(loop=loop)
self.send = send #ugh what if i want to RECEIVE though.
#not sure what the use case would be but...?
@asyncio.coroutine
def connect(self, port=None):
if not self.send:
server = self.current_server = self.network.servers[0]
self._reader, self._writer = yield from server.connect(self.loop)
self._read_loop_task = asyncio.Task(self._start_read_loop())
asyncio.async(self._read_loop_task, loop=self.loop)
else:
self._waiting = asyncio.Lock()
yield from self._waiting.acquire()
if port:
self.network = yield from asyncio.start_server(self._handle_client,
host=socket.gethostbyname(socket.gethostname()), port=port, loop=self.loop)
else:
logger.error("No port provided for send")
@asyncio.coroutine
def _handle_client(self, client_reader, client_writer):
self._reader = client_reader
self._writer = client_writer
self._waiting.release()
self._read_loop_task = asyncio.Task(self._start_read_loop())
asyncio.async(self._read_loop_task, loop=self.loop)
@asyncio.coroutine
def disconnect(self):
yield from self._writer.drain()
self._writer.write_eof()
self._read_loop_task.cancel()
yield from self._read_loop_task
while not self._reader.at_eof():
yield from self._reader.readline()
if self.send:
self.network.close()
@asyncio.coroutine
def _start_read_loop(self):
if not self.send: #acks don't really do anything so don't listen for them
while not self._reader.at_eof():
try:
yield from self._read_message()
except CancelledError:
return
except Exception:
logger.exception("Smothering exception in DCC read loop")
@asyncio.coroutine
def _read_message(self):
line = yield from self._reader.readline()
m = re.match(b'(.*)(\r|\n|\r\n)$', line)
assert m
line = m.group(1)
message = DCCMessage.parse(line)
logger.debug("recv: %r", message)
event = DirectMessage(self, message)
self.read_queue.put_nowait((message, event))
@asyncio.coroutine
def read_event(self):
message, event = yield from self.read_queue.get()
return event
@asyncio.coroutine
def say(self, message, target=None, no_respond=None):
self.send_message(message)
@asyncio.coroutine
def send_message(self, message):
message = DCCMessage(message)
logger.debug("sent: %r", message)
self._writer.write(message.render().encode('utf8') + b'\r\n')
@asyncio.coroutine
def transfer(self, path):
yield from self._waiting.acquire()
f = open(str(path), 'rb')
block = b'\x01'
while block != b'':
block = f.read(1024)
self._writer.write(block)
f.close()
self._waiting.release()
return True
示例8: __init__
# 需要导入模块: from asyncio.queues import Queue [as 别名]
# 或者: from asyncio.queues.Queue import put_nowait [as 别名]
class StreamConnection:
def __init__(self, sr, sw, *, loop=None):
if not loop:
loop = asyncio.get_event_loop()
self._loop = loop
self._sr = sr
self._sw = sw
self._msgs = Queue(loop=loop)
self._worker = loop.create_task(self._run())
@asyncio.coroutine
def _run(self):
while self.alive():
try:
data = yield from self._sr.readline()
if data and len(data):
self._msgs.put_nowait(self._convert(data))
except asyncio.CancelledError:
logger.debug("readline from stream reader was cancelled.")
except ConnectionError:
logger.debug("connection error")
break
logger.debug("connection closed")
def _convert(self, data):
return data.strip()
@asyncio.coroutine
def recv(self):
try:
return self._msgs.get_nowait()
except QueueEmpty:
pass
# Wait for a message until the connection is closed
next_message = self._loop.create_task(self._msgs.get())
done, pending = yield from asyncio.wait(
[next_message, self._worker],
loop=self._loop, return_when=asyncio.FIRST_COMPLETED)
if next_message in done:
return next_message.result()
else:
next_message.cancel()
def send(self, data):
if not self.alive():
raise ConnectionError("connection was closed.")
try:
data = data + b'\n'
self._sw.write(data)
except OSError:
raise ConnectionError("can't send data.")
except Exception:
logger.debug("Q___Q")
def alive(self):
return not self._sr.at_eof()
@asyncio.coroutine
def drain():
yield from self._sw.drain()
@asyncio.coroutine
def close(self):
if self.alive():
try:
yield from self._sw.drain()
self._sw.write_eof()
except ConnectionError:
pass
else:
self._sr.feed_eof()
self._sw.close()
self._worker.cancel()
示例9: DywypiShell
# 需要导入模块: from asyncio.queues import Queue [as 别名]
# 或者: from asyncio.queues.Queue import put_nowait [as 别名]
#.........这里部分代码省略.........
('flow', prompt),
],
focus_item=prompt,
)
def build_palette(self):
return [
('default', 'default', 'default'),
('logging-debug', 'dark gray', 'default'),
('logging-info', 'light gray', 'default'),
('logging-warning', 'light red', 'default'),
('logging-error', 'dark red', 'default'),
('logging-critical', 'light magenta', 'default'),
('shell-input', 'light gray', 'default'),
('bot-output', 'default', 'default'),
('bot-output-label', 'dark cyan', 'default'),
]
def unhandled_input(self, key):
# Try passing the key along to the listbox, so pgup/pgdn still work.
# Note that this is a Pile method specifically, and requires an index
# rather than a widget
# TODO no indication whether we're currently scrolled up. scroll back
# to bottom after x seconds with no input?
listsize = self.widget.get_item_size(
self.urwid_loop.screen_size, 0, False)
key = self.pane.keypress(listsize, key)
if key:
# `key` gets returned if it wasn't consumed
self.add_log_line(key)
def start(self):
super(DywypiShell, self).start()
#self.hub.network_connected(self.network, self)
def add_log_line(self, line, color='default'):
# TODO generalize this color thing in a way compatible with irc, html, ...
# TODO i super duper want this for logging, showing incoming/outgoing
# messages in the right colors, etc!!
self._print_text((color, line.rstrip()))
def _print_text(self, *encoded_text):
self.pane.body.append(urwid.Text(list(encoded_text)))
self.pane.set_focus(len(self.pane.body) - 1)
# TODO should this just mark dirty??
self.urwid_loop.draw_screen()
def handle_line(self, line):
"""Deal with a line of input."""
try:
self._handle_line(line)
except Exception as e:
log.exception(e)
def _handle_line(self, line):
"""All the good stuff happens here.
Various things happen depending on what the line starts with.
Colon: This is a command; pretend it was sent as a private message.
"""
# Whatever it was, log it
self.pane.body.append(urwid.Text(['>>> ', ('shell-input', line)]))
if line.startswith(':'):
command_string = line[1:]
# TODO rather we didn't need raw_message...
raw_message = ShellMessage(self.me.name, command_string)
event = Message(self, raw_message)
self.event_queue.put_nowait(event)
def _send_message(self, target, message, as_notice=True):
# TODO cool color
self.add_log_line(message)
@asyncio.coroutine
def say(self, target, message):
# TODO target should probably be a peer, eh
if target == self.you.name:
prefix = "bot to you: "
else:
prefix = "bot to {}: ".format(target)
self._print_text(('bot-output-label', prefix), ('bot-output', message))
def format_transition(self, current_style, new_style):
# TODO wait lol shouldn't this be converting to urwid-style tuples
if new_style == Style.default():
# Just use the reset sequence
return '\x1b[0m'
ansi_codes = []
if new_style.fg != current_style.fg:
ansi_codes.append(FOREGROUND_CODES[new_style.fg])
if new_style.bold != current_style.bold:
ansi_codes.append(BOLD_CODES[new_style.bold])
return '\x1b[' + ';'.join(ansi_codes) + 'm'
示例10: WebSocketCommonProtocol
# 需要导入模块: from asyncio.queues import Queue [as 别名]
# 或者: from asyncio.queues.Queue import put_nowait [as 别名]
#.........这里部分代码省略.........
A ping may serve as a keepalive.
"""
# Protect against duplicates if a payload is explicitly set.
if data in self.pings:
raise ValueError("Already waiting for a pong with the same data")
# Generate a unique random payload otherwise.
while data is None or data in self.pings:
data = struct.pack('!I', random.getrandbits(32))
self.pings[data] = asyncio.Future()
yield from self.write_frame(OP_PING, data)
return self.pings[data]
@asyncio.coroutine
def pong(self, data=b''):
"""
This coroutine sends a pong.
An unsolicited pong may serve as a unidirectional heartbeat.
"""
yield from self.write_frame(OP_PONG, data)
# Private methods - no guarantees.
@asyncio.coroutine
def run(self):
# This coroutine guarantees that the connection is closed at exit.
yield from self.opening_handshake
while not self.closing_handshake.done():
try:
msg = yield from self.read_message()
if msg is None:
break
self.messages.put_nowait(msg)
except asyncio.CancelledError:
break
except WebSocketProtocolError:
yield from self.fail_connection(1002)
except asyncio.IncompleteReadError:
yield from self.fail_connection(1006)
except UnicodeDecodeError:
yield from self.fail_connection(1007)
except PayloadTooBig:
yield from self.fail_connection(1009)
except Exception:
yield from self.fail_connection(1011)
raise
yield from self.close_connection()
@asyncio.coroutine
def read_message(self):
# Reassemble fragmented messages.
frame = yield from self.read_data_frame(max_size=self.max_size)
if frame is None:
return
if frame.opcode == OP_TEXT:
text = True
elif frame.opcode == OP_BINARY:
text = False
else: # frame.opcode == OP_CONT
raise WebSocketProtocolError("Unexpected opcode")
# Shortcut for the common case - no fragmentation
if frame.fin:
return frame.data.decode('utf-8') if text else frame.data
示例11: events
# 需要导入模块: from asyncio.queues import Queue [as 别名]
# 或者: from asyncio.queues.Queue import put_nowait [as 别名]
#.........这里部分代码省略.........
# If we get here, we expected this response, and should keep
# feeding into this future.
collected.append(message)
if finish:
# Done, one way or another
self._message_waiters.popleft()
if message.is_error:
fut.set_exception(IRCError(message))
else:
fut.set_result(collected)
@asyncio.coroutine
def _read_message(self):
"""Internal dispatcher for messages received from the server."""
line = yield from self._reader.readline()
assert line.endswith(b"\r\n")
line = line[:-2]
# TODO valerr, unicodeerr
message = IRCMessage.parse(line.decode(self.charset))
log.debug("recv: %r", message)
# TODO unclear whether this should go before or after _handle_foo
self._possibly_gather_message(message)
# Boy do I ever hate this pattern but it's slightly more maintainable
# than a 500-line if tree.
handler = getattr(self, "_handle_" + message.command, None)
event = None
if handler:
event = handler(message)
self.read_queue.put_nowait((message, event))
def _handle_PING(self, message):
# PONG
self.send_message("PONG", message.args[-1])
def _handle_RPL_WELCOME(self, message):
# Initial registration: do autojoins, and any other onconnect work
for channel_name in self.network.autojoins:
asyncio.async(self.join(channel_name), loop=self.loop)
def _handle_RPL_ISUPPORT(self, message):
me, *features, human_text = message.args
for feature_string in features:
feature, _, value = feature_string.partition("=")
if value is None:
value = True
self.features[feature] = value
if feature == "NICKLEN":
self.len_nick = int(value)
elif feature == "CHANNELLEN":
self.len_channel = int(value)
elif feature == "KICKLEN":
self.len_kick = int(value)
elif feature == "TOPICLEN":
self.len_topic = int(value)
elif feature == "AWAYLEN":
self.len_away = int(value)
elif feature == "WATCH":
self.max_watches = int(value)
elif feature == "CHANTYPES":
示例12: events
# 需要导入模块: from asyncio.queues import Queue [as 别名]
# 或者: from asyncio.queues.Queue import put_nowait [as 别名]
#.........这里部分代码省略.........
for fut, (waiting_on, collected) in self._message_waiters.items():
# TODO this needs to handle error codes too, or the future will
# linger forever! potential problem: if the server is lagging
# behind us, an error code might actually map to a privmsg we tried
# to send (which has no success response) and we'll get all fucked
# up. i don't know if there's any way to solve this.
# TODO hey stupid question: after we've seen ANY of the waited-on
# messages, should we pipe all subsequent messages into that future
# until we see the one that's supposed to end it? something like
# a forced JOIN could screw up a join attempt, for example, but if
# we're getting RPL_TOPIC when we didn't actually ask for the
# topic, THEN we know we're definitely in the join sequence.
# TODO also given normal irc response flow, i'm pretty sure we
# should only ever need to check the first pending future. there's
# no way we should need to skip around.
# TODO maybe give these a timeout so a bad one doesn't fuck us up
# forever
if message.command in waiting_on:
collected.append(message)
if waiting_on[message.command] == 'end':
fut.set_result(collected)
del self._message_waiters[fut]
elif waiting_on[message.command] == 'error':
fut.set_exception(IRCError(message))
del self._message_waiters[fut]
break
# Boy do I ever hate this pattern but it's slightly more maintainable
# than a 500-line if tree.
handler = getattr(self, '_handle_' + message.command, None)
event = None
if handler:
event = handler(message)
self.read_queue.put_nowait((message, event))
def _handle_PING(self, message):
# PONG
self.send_message('PONG', message.args[-1])
def _handle_RPL_WELCOME(self, message):
# Initial registration: do autojoins, and any other onconnect work
self.network.hostname = message.args[1].rsplit(sep='@')[-1]
for channel_name in self.network.autojoins:
asyncio.async(self.join(channel_name), loop=self.loop)
def _handle_RPL_ISUPPORT(self, message):
me, *features, human_text = message.args
for feature_string in features:
feature, _, value = feature_string.partition('=')
if value is None:
value = True
self.features[feature] = value
if feature == 'NICKLEN':
self.len_nick = int(value)
elif feature == 'CHANNELLEN':
self.len_channel = int(value)
elif feature == 'KICKLEN':
self.len_kick = int(value)
elif feature == 'TOPICLEN':
self.len_topic = int(value)
elif feature == 'AWAYLEN':
self.len_away = int(value)
elif feature == 'WATCH':
self.max_watches = int(value)