Friday, May 29, 2009

Learn Python Workshop

I'm going to be teaching an intro to Python workshop next month. It will consist of 3 3 hour days and will cover the basics of Python. Dates are June 15th, 17th, 19th. The workshop is free for all U of A students, staff, and faculty. I have never lead a workshop before, so it should be a lot of fun.

Register for the Python workshop

Wednesday, May 20, 2009

Real-time Flex messaging with AmFast

This example is very similar to the previous, but we're going to use AmFast's HTTP streaming channel to implement real-time flex messaging. Get the complete example code here.

First let's setup the Producer and Consumer in Actionscript.


// Configure the ChannelSet that
// messages will be sent and received over.
import mx.messaging.ChannelSet;

// To use HTTP streaming, the
// StreamingAMFChannel class must be used.
import mx.messaging.channels.StreamingAMFChannel;
var channelSet:ChannelSet = new ChannelSet();
var channel:StreamingAMFChannel = new StreamingAMFChannel("channel-name", "server-url");
channelSet.addChannel(channel);

// Setup a Consumer to receive messages.
import mx.messaging.Consumer;
var consumer:Consumer = new Consumer();

// The consumer's destination is the 'topic'
// name that the consumer will be subscribed to.
// The consumer will receive all messages
// published to the topic.
consumer.destination = "topic";

// Use the ChannelSet that was already created.
consumer.channelSet = channelSet;

// This event listener will be called whenever
// the consumer receives a message from the server.
consumer.addEventListener(MessageEvent.MESSAGE, newMsgHandler);

// The consumer won't start receiving messages
// until it is subscribed.
consumer.subscribe();

// Setup a Producer to publish messages.
import mx.messaging.Producer;
var producer:Producer = new Producer();
producer.destination = "topic";
producer.channelSet = channelSet;

// Create an Async message and send it
// to all other clients subscribed to the topic.
import mx.messaging.messages.AsyncMessage;
var msg:AsyncMessage = new AsynMessage();

// Set the message's body attribute to the
// object that is going to be published.
//
// In this case the object contains
// the X and Y coordinates of a Sprite.
msg.body = {'x': 10, 'y': 10};
producer.send(msg);

Next we'll setup the server.

# Create a ChannelSet to serve messages.
from amfast.remoting.channel import ChannelSet
from amfast.remoting.wsgi_channel import StreamingWsgiChannel
channel_set = ChannelSet()

# Each individual ChannelSet can use
# one or more Channels. When messages
# are published through the ChannelSet,
# they will be published to all subscribed clients,
# regardless of which Channel the clients
# are connected through.

# Create a HTTP streaming channel.
#
# When a client connects to a streaming channel,
# the HTTP connection remains open until the client
# disconnects. When messages are published,
# they are immediately dispatched to clients connected
# to HTTP streaming channels.
stream_channel = StreamingWsgiChannel('stream-channel')

# WsgiChannels objects are wsgi applications
# that can be served with any Wsgi server.
# CherryPy is being used in this example.
cherrypy.tree.graft(stream_channel, '/amf')

# Start the server.
# App() is your root controller class
# for non-AMF functions.
cherrypy.quickstart(App(), '/')

# That's it, our server is up and running.
# It's that simple.

To test the example, download the full code from the repo. To run the example you'll need to install AmFast and CherryPy or Twisted 1st.

# To server the example with cherrypy
python cp_server.py

# To server the example with Twisted
twistd -noy twisted_server.tac

Open two browser windows and browse to 'http://localhost:8000'. Click the 'Subscribe' button in both windows. In the 1st window click on the 'Master' button. In the 1st window, click on the yellow circle, and drag the circle around the screen. As the circle is dragged around the screen, the position of the circle will be updated in the 2nd window. Pretty cool stuff.

Saturday, May 16, 2009

Create a chat client and server with Flex and Python

In this example we'll create a simple Flex chat client that uses Producer/Consumer messaging to send and receive messages through a Python server. The server will use AmFast's HTTP polling and long-polling channels. Get the complete example code here.

First let's setup the Producer and Consumer in Actionscript.

// Configure the ChannelSet that
// messages will be sent and received over.
import mx.messaging.ChannelSet;
import mx.messaging.channels.AMFChannel;
var channelSet:ChannelSet = new ChannelSet();
var channel:AMFChannel = new AMFChannel("channel-name", "server-url");
channelSet.addChannel(channel);

// Setup a Consumer to receive messages.
import mx.messaging.Consumer;
var consumer:Consumer = new Consumer();

// The consumer's destination is the 'topic'
// name that the consumer will be subscribed to.
// The consumer will receive all messages
// published to the topic.
consumer.destination = "topic";

// Use the ChannelSet that was already created.
consumer.channelSet = channelSet;

// This event listener will be called whenever
// the consumer receives a message from the server.
consumer.addEventListener(MessageEvent.MESSAGE, newMsgHandler);

// The consumer won't start receiving messages
// until it is subscribed.
consumer.subscribe();

// Setup a Producer to publish messages.
import mx.messaging.Producer;
var producer:Producer = new Producer();
producer.destination = "topic";
producer.channelSet = channelSet;

// Create an Async message and send it
// to all other clients subscribed to the topic.
import mx.messaging.messages.AsyncMessage;
var msg:AsyncMessage = new AsynMessage();

// Set the message's body attribute to the
// object that is going to be published.
//
// In this case the object is a String,
// but the message body can be any
// type of object.
msg.body = "This is being published!";
producer.send(msg);



Next we'll setup the server.

# Create a ChannelSet to serve messages.
from amfast.remoting.channel import ChannelSet
from amfast.remoting.wsgi_channel import WsgiChannel
channel_set = ChannelSet()

# Each individual ChannelSet can use
# one or more Channels. When messages
# are published through the ChannelSet,
# they will be published to all subscribed clients,
# regardless of which Channel the clients
# are connected through.

# Create s standard polling channel.
polling_channel = WsgiChannel('poll-channel')

# A long-polling channel is created similar
# to a normal channel, but the wait_interval
# argument must be set to -1.
long_channel = WsgiChannel('long-channel', wait_interval=-1)

# WsgiChannels objects are wsgi applications
# that can be served with any Wsgi server.
# CherryPy is being used in this example.
cherrypy.tree.graft(polling_channel, '/amf')
cherrypy.tree.graft(long_channel, '/longPoll')

# Start the server.
# App() is your root controller class
# for non-AMF functions.
cherrypy.quickstart(App(), '/')

# That's it, our server is up and running.
# It's that simple.


To test the example, download the full code from the repo. To run the example you'll need to install AmFast and CherryPy or Twisted 1st.


# To server the example with cherrypy
python cp_server.py

# To server the example with Twisted
twistd -noy twisted_server.tac


Open two browser windows and browse to 'http://localhost:8000'. In the 1st window set the messaging url to 'http://localhost:8000/amf' to use the polling channel. In the 2nd window set the messaging url to 'http://localhost:8000/longPoll' to use the long-polling channel. Click the 'Subscribe' button in both windows. Enter a message in the message entry box, and press the 'Publish' button to publish the message. The published message will appear in both clients.

Friday, May 15, 2009

'Pushing' messages to Flex clients with AmFast

One of the coolest aspects of Flex development is the ability to 'push' messages from the server to clients. With the newest release of AmFast, you can finally utilize this capability with all of the goodness of Python. This will be the 1st of 3 posts describing how you can use the AmFast Flash remoting package to push messages to Flex clients from a Python server.

AmFast supports pushing messages to clients over HTTP using 3 different strategies: polling, long-polling, and streaming. Here is a good article describing the differences between those strategies. Go ahead and skip past the XML configuration sections, since you won't need any XML to configure AmFast :)

Streaming channels deliver messages in real time, but also consume the most server resources. Standard polling consumes the least amount of server resources, but is also the slowest of the three strategies. Long-polling sits in the middle and offers a nice compromise between latency and resource consumption.

AmFast has built-in support for using any of the 3 messaging strategies with either a multi-threaded WSGI server, or the Twisted web framework. One thing to think about when implementing a multi-threaded server is that any client using long-polling or streaming may consume a thread for a significant amount of time, even if all it's doing is waiting for a new message. I haven't done any tests, but I'm guessing that Twisted's single-threaded, asynchronous design can handle more concurrent connections then a multi-threaded implementation.

On the client side, the Actionscript Consumer class is used to receive messages from a server, and the Producer class is used to send messages to a server. Any type of object can be pushed to clients, so the same technology can be used to build many different types of applications.

In the next post I'll explain the details of using AmFast's HTTP polling and HTTP long-polling channels to create a simple chat client. In the following post I'll show an example of using HTTP streaming to create an app where a master client can manipulate a graphical entity on the screen, and changes are replicated to all other subscribed clients.

Saturday, May 9, 2009

AmFast 0.3.0 Released!

The latest version of AmFast is out. In addition to the changes listed below, the documentation has been updated, and there are several new examples.

remoting
  • Producer/Consumer messaging via HTTP polling.
  • Channels and ChannelSets allow resources to be exposed in multiple ways.
  • Built in Channels for CherryPy, Twisted Web, and straight-up WSGI.
  • Easy to configure authentication for NetConnection and RemoteObject.
  • Connection objects hold session attributes tied to Flex client id.
  • Customizable Endpoints to encode/decode messages with external encoding/decoding libraries.
  • PyAmfEndpoint to encode/decode messages with pure Python, with no C compiler dependencies.

encode/decode
  • Read and write to file-like-objects or strings (using strings is much faster).
  • Automatic type conversion.
  • amfast.class_def.as_types.AsProxy and amfast.class_def.as_types.AsNoProxy allow overriding 'use_collections' and 'use_proxies' settings for a individual objects.
  • readExternal and writeExternal methods of the IEXTERNALIZABLE interface accept different parameters to make custom encodings easier.
  • amfast.encoder.Encoder and amfast.decoder.Decoder: Wrappers around amfast.encode and amfast.decode, so you don't need to pass the same arguments every time you encode or decode.

Wednesday, May 6, 2009

Plater 0.1.3 maintenance release

Plater 0.1.3 (laboratory information management package) maintenance release today. The release contains a bug fix that was affecting parsing of CSV plate maps.

Saturday, May 2, 2009

AmFast 0.3 release is coming soon

I've been working on AmFast 0.3 for a while now, and it looks like I should be able to release it next weekend. 0.3 has cool new features such as: Producer/Consumer messaging, pure-Python encoding and decoding using PyAmf, and a bunch of other cool stuff.

The coding is done, and I'm working on documentation, testing, and a couple of new example applications.