Introduction to the Networks Tutorial

The Project

This tutorial walks you through how to make an IRC bot with Twisted. You will be introduced to testing, logging, an overview of how the internet works, as well as event-driven programming, different internet protocols, and making a portable application.

The project’s code is based off of Jessamyn Smith’s IRC bot – the talkbackbot, where if anyone says “That’s what she said” in an IRC channel, the bot replies with a notable quote from a woman (that’s what she really said!).

Intro to IRC

IRC stands for Internet Relay Chat, and is a protocol for live messaging over the internet. Specifically, the IRC protocol is within the application layer (just a simple abstraction of types of protocols). Other examples of internet protocols within the application layer are HTTP, IMAP, SMTP, POP, SSH, among many others.

IRC uses TCP, Transmission Control Protocol (another protocol!). TCP is within the transport layer, as opposed to application later. Another popular transportation layer protocol is UDP.

If you have heard of IRC before, you may think it’s an antiquated means of communication. Created in 1988, it remains one of the most popular protocols for instant messaging within many aspects of the tech community.

There are many IRC networks, the most popular in terms of users at peak hours are freenode, IRCNet, and QuakeNet.

IRCHelp is a great resource for learning IRC. PyLadies also has a great introduction on how to setup and use IRC. Of the Python community, some frequent channels visited are #python, #django, #python-dev, #twisted, and of course, #pyladies, all on Freenode.

For more information, Jessica McKellar gave a great talk at PyCon 2013 about How the Internet Works, with her slides here. She gives an overview of what happens when you click through your browser, what a protocol is, DNS, and generally how to communicate over the internet.

Intro to Twisted

According to Twisted’s website, Twisted is an “event-driven networking engine written in Python”. OK…what does that mean?

Event-driven programming

Event-driven programming simply means that the flow of the program is determined by events. Events may be a click of the mouse, a message from another program, a response from a server, etc. The primary activity is a reaction to receiving a certain event(s).

Glyph, the author of Twisted, gave a great talk on event-driven architecture at PyCon 2013. He describes how to approach thinking about events and callbacks the right way. Essentially, an event is just a function call that you asked for. Glyph’s slides encapsulates it well:

  • When a user clicks a button, then call this function.
  • When a user answers this question, call this function.
  • When a network answers a question, call this function.
  • When a network sends me data, call this function.

Programming Paradigms

Some paradigms include object-oriented, imperative, and functional, all of which can use event-driven programming. If you are curious about how to employ different programming paradigms for different problems, check out How to Design Programs.

Intro to Logging

Logging is quite important for applications. Transferring money, the black box on an airplane, cell phone bills - they all log actions to be referenced and checked later. As such, logging is quite important for developing, debugging, maintaining, and running systems and applications.

There is the logging module in Python’s standard library, and a great how-to write up for the logging module.

But Twisted has its own logging module, log. The initial reason that Twisted doesn’t use the logging module from the Python standard library is that the Twisted logging module predates the stdlib one. There are many reasons that Twisted hasn’t moved to the stdlib logging module which you can read here.

You may start out simply adding print statements to your application, but this isn’t ideal for anything beyond a very basic script. print does not allow you to set up different importance levels, e.g. DEBUG, INFO, WARN, ERROR, CRITICAL, or FAIL; it’s an all or nothing with print.

Identifying which level of importance to log a message at can get some getting use to. Use the debug level for granular information, such as printing out variables that change within a for-loop:

1
2
3
4
def some_awesome_function(items):
    for i, item in enumerate(items):
        # do some complex computation/iteration
        logger.debug('%s iteration, item=%s', i, item)

Use info for routines and such, like starting or connecting to a server:

1
2
3
4
def start_IMAP_service():
    logger.info('Starting IMAP service at port %s ...', port)
    service.start()
    logger.info('IMAP Service is started')

Use warn for important events happen, but no error has occurred, like a password that was incorrectly inputted. Finally, use error for when an exception is thrown, user isn’t found in the database, connectivity issue, etc. As the admin of an application with a logging mechanism, you would setup your desired level of logs in some configuration for instance, if you only want to see errors, you would ideally set a configuration value to something like debug_level=error.

These above examples use Python’s logging module. For our tutorial, we’ll use Twisted’s log module, which has slightly different syntax when passing in log levels.

Intro to Testing

Very similar to logging, testing is also quite important for your code base. Writing tests in parallel to writing code is considered a good habit. Submitting features and patches to projects without tests can be a big faux-pas.

There are different types of testing, and with this tutorial we will focus on unit testing.

A unit test just focuses on one tiny bit of functionality to prove correct behavior based on inputs, and should be independent of other unit tests.

An example of a unit test using Pythons unittest module, taken from python-guide.org:

1
2
3
4
5
6
7
8
import unittest

def fun(x):
    return x + 1

class MyTest(unittest.TestCase):
    def test(self):
        self.assertEqual(fun(3), 4)

The main part here is assertEqual(fun(3), 4), where we feed fun the number 3. The test will pass if the return value of fun(3) == 4, else it will fail.

We will be using Twisted’s own unit testing framework that is built upon Python’s unittest module with the added ability to test event-driven code.

Approaching the tutorial

We will first knock out the simple items by addressing the global variables/settings for our IRC bot. We’ll then build a quick function to select quotes (a list of quotes can be found in the GitHub repo).

Then we’ll approach the making of the bot module by first creating a class to create bots (a factory class), and then another class to define the behavior of the bot. We will also write a quick plugin to easily create and start up our bot from the command line.

Lastly, we will write tests for the expected behavior of our talkback bot application.

All set? Let’s begin!