Skip to content

eamartin/roadmap

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

19 Commits
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Introduction

Roadmap is a routing library powered by regular expressions and coroutines. Roadmap was created to quickly map large amounts of input to functions. In the particular case that sparked Roadmap's development, I was writing an IRC bot and I wanted a fast (to code and to execute) way to map input strings to functions. Beyond an IRC bot, I could also picture Roadmap being used to process data from a web API, user input, a socket, or really any stream of data.

Examples

Let's create a basic roadmap.Router instance to route email addresses. We will route them by subdomain. The goal is to respond to basic commands from string. We only want the bot to respond to commands, which will all be prefixed by !. The output of this Roadmap will just be printing. Therefore, it is logical for each handler to return a string. Here we go:

import roadmap.Router

def my_processor(string):
    print string

r = roadmap.Router(my_processor)

@r.destination(r'^echo (.*)', pass_obj=False)
def echo(message):
    return message

@r.destination(r'^divide ([0-9]+) ([0-9]+)', pass_obj=False)
def divide(dividend, divisor):
    return int(dividend) / float(divisor)

@r.destination(r'^test .*')
def test(string):
    return 'Input received: %s' % string

@r.destination(r'^intials (?P<last>),\W+(?P<first>)\W+(?P<middle>) ',\
                                                    pass_obj=False)
def initials(first, middle, last):
    return '%s. %s. %s.' % (first[0], middle[0], last[0])

for input in input_stream():
    if input.startswith('!'):
        r.route(input[1:])

Sorry this example is simple and extremely contrived, but it shows the main mechanics of Roadmap. Below, each part of the example is explained.

Initialization

def my_processor(string):
    print string

r = roadmap.Router(my_processor)

Each of the Router's function will be printable, and all we want to do with the output is print right now. The my_processor function could just as easily handle instances as it handles strings in this function, and it save to database or communicate over a socket rather than just printing. r is created as a new Router that will use my_processor.

Echo Function

@r.destination(r'echo (.*)', pass_obj=False)
def echo(message):
    return message

Any string that begins with echo will route to this function. pass_obj is set to False, so the full input string (including echo) will not be passed to the function, because there is no need for every message to being with echo. However, the regular expression does contain a group (indicated by the parenthesis) that will match any string. Unnamed groups are passed to the function in the order they are assigned. The regular expression group becomes message and is returned by the function, and then printed by my_processor.

Add Function

@r.destination(r'^divide ([0-9]+) ([0-9]+)', pass_obj=False)
def divide(dividend, divisor):
    return int(dividend) / double(divisor)

add follows the exact same rules as echo, but simply shows that multiple unnamed groups can be used. The first group becomes dividend, the second group becomes divisor. Notice the type casting, because regular expression matches return strings.

Test Function

@r.destination(r'^test .*')
def test(string):
    return 'Input received: %s' % string

Note that no groups are captured in the regular expression. However, pass_obj is not specified, and defaults to True. Therefore, the string passed to roadmap.Router.route where will be passed to test as string.

Initials Function

@r.destination(r'^intials (?P<last>),\W+(?P<first>)\W+(?P<middle>) ',\
                                                    pass_obj=False)
def initials(first, middle, last):
    return '%s. %s. %s.' % (first[0], middle[0], last[0])

This is how named groups are handled by Roadmap. The order in the regular expression does not have to correspond to the order of the parameters.

Calling ~roadmap.Router.route

for in_string in input_stream():
    if in_string.startswith('!'):
        r.route(in_string[1:])

This calls ~roadmap.Router.route with the ! stripped from the input string. Notice that roadmap.Router.route returns no value.

About

Regex based routing for python.

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages