Skip to content

Commit

Permalink
Merge pull request #109 from theunkn0wn1/doc/9.0
Browse files Browse the repository at this point in the history
Update documentation for v9.0
  • Loading branch information
theunkn0wn1 authored Jan 12, 2019
2 parents 845429f + 22cb8e5 commit 817e715
Show file tree
Hide file tree
Showing 4 changed files with 33 additions and 55 deletions.
19 changes: 0 additions & 19 deletions docs/api/async.rst

This file was deleted.

1 change: 0 additions & 1 deletion docs/api/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,4 @@ API reference
:maxdepth: 2

client
async
features
6 changes: 3 additions & 3 deletions docs/intro.rst
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ Introduction to pydle

What is pydle?
--------------
pydle is an IRC library for Python 3.4 and up.
pydle is an IRC library for Python 3.5 and up.

Although old and dated on some fronts, IRC is still used by a variety of communities as the real-time communication method of choice,
and the most popular IRC networks can still count on tens of thousands of users at any point during the day.
Expand Down Expand Up @@ -35,8 +35,8 @@ All dependencies can be installed using the standard package manager for Python,

Compatibility
-------------
pydle works in any interpreter that implements Python 3.2 or higher. Although mainly tested in CPython_, the standard Python implementation,
there is no reason why pydle itself should not work in alternative implementations like PyPy_, as long as they support the Python 3.2 language requirements.
pydle works in any interpreter that implements Python 3.5 or higher. Although mainly tested in CPython_, the standard Python implementation,
there is no reason why pydle itself should not work in alternative implementations like PyPy_, as long as they support the Python 3.5 language requirements.

.. _CPython: https://python.org
.. _PyPy: http://pypy.org
62 changes: 30 additions & 32 deletions docs/usage.rst
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,8 @@ pydle will automatically take care of ensuring that the connection persists, and
import pydle
client = pydle.Client('MyBot')
# Client.connect() is a blocking function.
client.connect('irc.freenode.net', tls=True)
# Client.connect() is a coroutine.
await client.connect('irc.freenode.net', tls=True)
client.handle_forever()
Adding functionality
Expand All @@ -33,17 +33,17 @@ To truly start adding functionality to the client, subclass :class:`pydle.Client
class MyClient(pydle.Client):
""" This is a simple bot that will greet people as they join the channel. """
def on_connect(self):
super().on_connect()
async def on_connect(self):
await super().on_connect()
# Can't greet many people without joining a channel.
self.join('#kochira')
await self.join('#kochira')
def on_join(self, channel, user):
super().on_join(channel, user)
self.message(channel, 'Hey there, {user}!', user=user)
async def on_join(self, channel, user):
await super().on_join(channel, user)
await self.message(channel, 'Hey there, {user}!', user=user)
client = MyClient('MyBot')
client.connect('irc.freenode.net', tls=True)
await client.connect('irc.freenode.net', tls=True)
client.handle_forever()
This trivial example shows a few things:
Expand Down Expand Up @@ -75,14 +75,14 @@ and handle them within a single loop.
class MyClient(pydle.Client):
""" This is a simple bot that will greet people as they join the channel. """
def on_connect(self):
super().on_connect()
async def on_connect(self):
await super().on_connect()
# Can't greet many people without joining a channel.
self.join('#kochira')
await self.join('#kochira')
def on_join(self, channel, user):
super().on_join(channel, user)
self.message(channel, 'Hey there, {user}!', user=user)
async def on_join(self, channel, user):
await super().on_join(channel, user)
await self.message(channel, 'Hey there, {user}!', user=user)
# Setup pool and connect clients.
pool = pydle.ClientPool()
Expand Down Expand Up @@ -138,12 +138,12 @@ Asynchronous functionality
Some actions inevitably require blocking and waiting for a result. Since pydle is an asynchronous library where a client runs in a single thread,
doing this blindly could lead to issues like the operation blocking the handling of messages entirely.

Fortunately, pydle implements coroutines_ which allow you to handle a blocking operation almost as if it were a regular operation,
Fortunately, pydle utilizes asyncio coroutines_ which allow you to handle a blocking operation almost as if it were a regular operation,
while still retaining the benefits of asynchronous program flow. Coroutines allow pydle to be notified when a blocking operation is done,
and then resume execution of the calling function appropriately. That way, blocking operations do not block the entire program flow,
and then resume execution of the calling function appropriately. That way, blocking operations do not block the entire program flow.

In order for a function to be declared as a coroutine, it has to be decorated using the :func:`pydle.coroutine` decorator.
It can then call functions that would normally block using Python's ``yield from`` operator.
In order for a function to be declared as a coroutine, it has to be declared as an ``async def`` function or decorated with the :meth:`asyncio.coroutine` decorator.
It can then call functions that would normally block using Python's ``await`` operator.
Since a function that calls a blocking function is itself blocking too, it has to be declared a coroutine as well.

.. hint::
Expand All @@ -168,12 +168,12 @@ the act of WHOISing will not block the entire program flow of the client.
that would be invalidated upon parting, quitting or changing nicknames.
"""
def on_connect(self):
super().on_connect()
async def on_connect(self):
await super().on_connect()
self.join('#kochira')
@pydle.coroutine
def is_admin(self, nickname):
await def is_admin(self, nickname):
"""
Check whether or not a user has administrative rights for this bot.
This is a blocking function: use a coroutine to call it.
Expand All @@ -184,29 +184,27 @@ the act of WHOISing will not block the entire program flow of the client.
# Check the WHOIS info to see if the source has identified with NickServ.
# This is a blocking operation, so use yield.
if source in ADMIN_NICKNAMES:
info = yield from self.whois(source)
info = await self.whois(source)
admin = info['identified']
return admin
@pydle.coroutine
def on_message(self, target, source, message):
super().on_message(target, source, message)
async def on_message(self, target, source, message):
await super().on_message(target, source, message)
# Tell a user if they are an administrator for this bot.
if message.startswith('!adminstatus'):
admin = yield from self.is_admin(source)
admin = await self.is_admin(source)
if admin:
self.message(target, '{source}: You are an administrator.', source=source)
else:
self.message(target, '{source}: You are not an administrator.', source=source)
Writing your own blocking operation that can work with coroutines is trivial:
just make your blocking method return a :class:`pydle.Future` instance (without the act of creating and returning the Future itself being blocking),
and any coroutine yielding it will halt execution until the returned future is resolved, using either
:meth:`pydle.Future.set_result` or :meth:`pydle.Future.set_exception`, while pydle can still handle everything else.
Simply use the existing asyncio apis: https://docs.python.org/3.7/library/asyncio-task.html#coroutines-and-tasks


You can create a :class:`pydle.Future` instance that belongs to the client by calling :meth:`pydle.async.EventLoop.create_future`.

.. _coroutines: https://en.wikipedia.org/wiki/Coroutine

0 comments on commit 817e715

Please sign in to comment.