Package: tgext.socketio
About tgext.socketiotgext.socketio provides an easy way to implement SocketIO in TurboGears2.
SocketIO support is provided by gevent-socketio and specific SocketIO server
based on gevent is provided.Installingtgextsocketio can be installed from pypi:pip install tgext.socketioRunningSocketIO support requires a custom GEvent based HTTP server to work
correctly, remember to edit yourdevelopment.iniand add:# SOCKETIO doesn't work with debug mode
debug = false

[server:main]
use = egg:tgext.socketio#socketio
socketio_resource = socketio

host = 127.0.0.1
port = 8080tgext.socketio#socketiois the server provided by tgext.socketio
to correctly support SocketIO, whilesocketio_resourceis the
path of yourSocketIOControllerclass.By defaultsocketiois used so you can mount aSocketIOControllersubclass under theRootControlleror you can mount it in any other location
and change yoursocketio_resourceoption.Using SocketIOControllerSocketIOControllerworks like any other TurboGears controller but supports
servingSocketIOTGNamespaceas sub controllers.SocketIOControllercan
also behave like any other TG Controller and provide normal web pages.SocketIOTGNamespaceare subclasses ofsocketio.namespace.Basenamespacewith
additional TurboGears features like@validateand@requiresupport.
Please keep in mind thatSocketIOTGNamespacerequires at least TurboGears2.3.1,
if you want to use a previous TurboGears version you can still useSocketIOControllerwith plainsocketio.namespace.Basenamespaceclasses.Usage ExampleThe following is a very simple example that handles two type of eventspingandfireballand response on real time to those:from tgext.socketio import SocketIOTGNamespace, SocketIOController

class PingPong(SocketIOTGNamespace):
    def on_ping(self, attack):
        if attack['type'] == 'fireball':
            for i in range(10):
                self.emit('pong',{'sound':'bang!'})
        else:
            self.emit('pong',{'sound':'pong'})


class SocketIO(SocketIOController):
    pingpong = PingPong

    @expose()
    def page(self, **kw):
        return '''
<html>
<body>
    <div>
        <a class="ping" href="#" data-attack="ping">Ping</a>
        <a class="ping" href="#" data-attack="fireball">Fireball</a>
        <a class="ping" href="#" data-attack="auto">Auto</a>
        <a class="ping" href="#" data-attack="error">Error</a>
    </div>
    <div id="result"></div>
    <script src="//cdnjs.cloudflare.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
    <script src="//cdnjs.cloudflare.com/ajax/libs/socket.io/0.9.16/socket.io.min.js"></script>
    <script>
    $(function(){
        var socket = io.connect('/pingpong', {'resource':'socketio'});
        socket.on('pong',function(data){
            $('#result').append(data.sound + '<br/>');
        });
        socket.on('error',function(error, info) {
            if (error == 'method_access_denied') { alert(info); }
            else { console.log(info); alert(error); }
        });
        $('.ping').click(function(event){
            event.preventDefault();
            socket.emit('ping',{'type':$(this).data('attack')});
        });
    });
    </script>
</body>
</html>
'''

class RootController(BaseController):
    socketio = SocketIO()Keep in mind that theSocketIOControllermust be mounted in the same location
specified bysocketio_resourceproperty in your configuration file.Using Validators and RequirementsSocketIOTGNamespacealso supports using@validateand@requireTurboGears decorators.The same example can be changed to provide validation and
permission checks with a few lines of code:from tg import validate, require, predicates
from tg.validation import TGValidationError
import random

class NoFireBallValidator(object):
    def to_python(self, value, *args, **kw):
        type_ = value['type']
        if type_ == 'auto':
            return {'type': random.choice(['ping', 'fireball'])}
        elif type_ == 'error':
            raise TGValidationError('Got an error!')

        return value


class PingPong(SocketIOTGNamespace):
    @require(predicates.not_anonymous())
    @validate({'attack': NoFireBallValidator()})
    def on_ping(self, attack):
        if attack['type'] == 'fireball':
            for i in range(10):
                self.emit('pong',{'sound':'bang!'})
        else:
            self.emit('pong',{'sound':'pong'})PubSub Supporttgext.socketiohas builtin support for PubSub paradigm based
onanypubsublibrary. If you want to use PubSub you should install
anypubsub throughpip install anypubsubor add it to your project
dependencies.PubSub support works by subclassing fromtgext.socketio.pubsub.PubSubTGNamespacethis special namespace permits clients to subscribe to channels usingsocket.emit('subscribe','channel_name')from the javascript interface.Whenever an user subscribes to a channel, the PubSubTGNamespace subclass will receive
a call forsubscribe_channelnamemethod, which can return if the user is permitted
to subscribe to the given channel or not (@requiredecorator can be used).
Thesubscribe_channelnamemethod can also return a different channel name if you want
to specify a subchannel.For each message published on the subscribed channel PubSubTGNamespace will emit apubblicationevent, which can be trapped by the socket.io client to perform required
actions.Publishing a message will be possible throughPubSubTGNamespace.publish.You can see a simple example providing a real time chat implemented on redis backend
inexamples/chat.py