Schurger.org

28 avril 2010

Les VOD de la salle Pleyel en RSS

Filed under: Code,Concerts,Python — Jean Schurger @ 21:52

La salle Pleyel diffuse ses concerts en vidéo à la demande, et un tel contenu mérite vraiment le détour. Cependant, les concerts ne sont disponibles que pendant une certaine période, et le seul moyen de se tenir informé des nouveautés à voir et écouter est d'aller régulièrement consulter la liste des concerts. C'est plutôt rébarbatif, un flux RSS aurait été très pratique.

Le petit bout de script suivant permet de parser la page des concerts, et produit des données au format RSS sur sa sortie standard.

Il suffit simplement de l'invoquer à partir d'un agrégateur pour pouvoir savoir quand un nouveau concert apparaît.

#!/usr/bin/python
# -*- coding: utf-8 -*-

import urllib2
from lxml import etree
from datetime import datetime
from PyRSS2Gen import RSSItem, RSS2
from md5 import md5

URL="http://www.sallepleyel.fr/francais/concerts/videos.aspx"
opener = urllib2.build_opener()
req =  urllib2.Request(URL)
html = etree.HTML(opener.open(req).read())
vodlist = filter(lambda ul: ul.attrib.get('class') == "vod",
                 html.findall(".//ul"))[0]
items = list()
for e in vodlist.findall(".//li"):
    a = e.findall(".//a")[1]
    title = a.find(".//strong").text
    link = a.attrib.get('onclick').split("'")[1]
    items.append(RSSItem(title = title,
                         link = link,
                         description=title,
                         guid=md5(link).hexdigest(),
                         pubDate=datetime.now()))
rss = RSS2(title = "Salle Pleyel en VOD",
           link = "http://www.sallepleyel.fr/francais/concerts/videos.aspx",
           description = "Concerts en vidéo à la demande (VOD)",
           lastBuildDate = datetime.now(),
           items = items)
print rss.to_xml()

Bonne écoute.

23 mars 2010

Bye bye MSN !

Filed under: Code,MSN,Python — Jean Schurger @ 19:03

Ça y est, je me débarasse de MSN. Mais comme je suis conscient que certaines personnes ne connaissent que ça, voici un petit compromis, qui plus est: éducatif.
Il sagit d'un répondeur automatique à MSN écrit en python, utilisant papyon.

(This is an auto responder for MSN, written in the python language, and using the papyon library)

#!/usr/bin/env python
# -*- coding: utf-8 -*-

import signal
import papyon
import papyon.event
import gobject
import logging

logging.basicConfig(level=logging.ERROR)

USER = "user@hotmail.com"
PASSWORD = "p4ssW0rD"
LAYUS = u"""

English bellow.

Bonjour,

  Ceci est une réponse automatique vous expliquant que je ne veux
  plus discuter par MSN.

  En résumé, MSN est fermé, et fonctionne mal.
  Il y a beaucoup d'alternatives libres et efficaces.

  Pour la version longue, lire:
  - http://schurger.org/la-vie-est-possible-sans-msn.html

  Je serai ravi de discuter:
  - En le protocol XMPP (Jabber, Google talk,...).
    (Mon identifiant est jean@schurger.org)
  - Sur IRC, via le serveur irc.freenode.net, mon nickname est jeansch
  - En utilisant la fonction clavardage de Facebook

  Amicalement,

  Jean.

---
 
Hello,

  This is an automatic answer telling why i don't want to chat using MSN.

  Basicaly, the reasons are that MSN is closed and works badly.
  There is a lot of realy great open alternatives.

  For more details, read:
  - http://schurger.org/life-is-possible-without-msn.html

  I'll be happy to chat using:
  - The XMPP protocol (Jabber, Google talk,...)
    (My id is jean@schurger.org)
  - On IRC, on server irc.freenode.net, my nickname is jeansch
  - Using the chat Facebook feature

  Friendly,

  Jean.
"""

class ClientEvents(papyon.event.BaseEventInterface):
   
    def on_client_state_changed(self, state):
        if state == papyon.event.ClientState.CLOSED:
            self._client.quit()
        elif state == papyon.event.ClientState.OPEN:
            self._client.profile.display_name = "Jean Schurger"
            self._client.profile.presence = papyon.Presence.ONLINE
            self._client.profile.personal_message = "Boycott de MSN"

    def on_invite_conversation(self, conversation):
        conversation.send_typing_notification()
        conversation.send_text_message(papyon.ConversationMessage(LAYUS))
        conversation.leave()
       
class Client(papyon.Client):
    def __init__(self, account, quit, http_mode=False):
        server = ('messenger.hotmail.com', 1863)
        self.quit = quit
        self.account = (USER, PASSWORD)
        papyon.Client.__init__(self, server)
        self._event_handler = ClientEvents(self)
        gobject.idle_add(self._connect)

    def _connect(self):
        self.login(*self.account)
        return False

def main():
    mainloop = gobject.MainLoop(is_running=True)
   
    def quit():
        mainloop.quit()
       
    def sigterm_cb():
        gobject.idle_add(quit)

    signal.signal(signal.SIGTERM, sigterm_cb)
    c = Client((USER, PASSWORD), quit)

    while mainloop.is_running():
        try:
            mainloop.run()
        except KeyboardInterrupt:
            quit()

if __name__ == '__main__':
    main()

10 mars 2010

Filed under: Code,Gnome,Python — Jean Schurger @ 1:59

Tired of typing your #freenode password when ERC is connecting ? You don't want to write you passwords as clear text in your .emacs files ?

Lets see how to store, passwords in the Gnome Keyring, and access it from Emacs. It only needs Pymacs and gnome-keyring python bindings.

  • Write a little module to read and write passwords. This module will be loaded my pymacs and its functions will be available from emacs-lisp. You may name your module 'gnome-keyring.py' and store it somewhere like '~/.emacs.d/pymacs/'
def get_password(name):
    import gnomekeyring as gk
    try:
        items = gk.find_items_sync(gk.ITEM_GENERIC_SECRET,
                                   dict(variable_name=name))
    except gk.NoMatchError:
        return None
    return items[0].secret
get_password.interaction = ""

def set_password(name, password):
    import gnomekeyring as gk
    gk.item_create_sync(gk.get_default_keyring_sync(),
                        gk.ITEM_GENERIC_SECRET,
                        "Emacs password", dict(variable_name=name),
                        password, True),
set_password.interaction = ""

  • Load the module using pymacs
(require 'pymacs)
(add-to-list '
pymacs-load-path "~/.emacs.d/pymacs/")
(pymacs-load "gnome-keyring" "gnome-keyring-")

  • Trying from the interactive emacs lisp mode (M-x ielm)
ELISP> (gnome-keyring-set-password "my-password" "p4$$w0rD")
nil
ELISP> (gnome-keyring-get-password "my-password")
"p4$$w0rD"

  • And now, an example for ERC
(setq erc-password (gnome-keyring-get-password "my-password"))
(setq erc-prompt-for-password nil)

Too easy ! :D

9 décembre 2009

Unit tests with Pylons and its XMLRPCController

Filed under: Python — Jean Schurger @ 1:37

Now that you have implemented a nice XMLRPCController in your pylons application, it's time to write unit tests covering it. The problem is that the xmlrpclib will try to make a real http connection to an address, but the TestApp used in your TestController is not a real server, and don't listen to any address.

Here is a quick way to enable the coverage of your XMLRPCController. Inspired by Kumar McMillan on this thread.

from StringIO import StringIO
import xmlrpclib
from xmlrpclib import ServerProxy
from mygreatapp.tests import TestController

# a fake httplib.HTTP using 'app' (see TestController.__init__())
class WSGILikeHTTP():
        def __init__(self, host, app):
                self.app = app
                self.headers = {}
                self.content = StringIO()
       
        def putrequest(self, method, handler):
                self.method = method
                self.handler = handler
       
        def putheader(self, key, value):
                self.headers[key] = value
       
        def endheaders(self):
                pass
       
        def send(self, body):
                self.body = body
       
        def getfile(self):
                return self.content

        def getreply(self):
                if self.method == "POST":
                        r = self.app.post(self.handler,
                                      headers=self.headers,
                                      params=self.body)
                        self.content = StringIO(r.response)
                return (200, None, None)

class WSGIAppTransport(xmlrpclib.Transport):
        # Only here to pass the 'app'
        def __init__(self, app):
                xmlrpclib.Transport.__init__(self)
                self.app = app

        # return the fake httplib.HTTP(host)
        def make_connection(self, host):
                host, extra_headers, x509 = self.get_host_info(host)
                return WSGILikeHTTP(host, self.app)

class TestApiController(TestController):
        def test_super_function(self):
                # URL _MUST_ starts with 'http' or 'https' (see xmlrpclib.py)
                server = ServerProxy('http://dummy/api',
                                     transport=WSGIAppTransport(self.app))
                server.super_function("Foo", "Bla", 42)

3 avril 2009

Quick Howto: Write/Install/Use a plugin in python with entry points

Filed under: Code,Python — Jean Schurger @ 19:52

Write a plugin

in a 'super_plugin' directory dedicaced to the plugin, create two files:

__init__.py with your plugin 'content' eg:

class Foo:
    def __init__(self):
        print "Foo plugin loaded !"

    def super_function(self):
        print "Bar !"

setup.py with your plugin description eg:

from setuptools import setup, find_packages

setup (
    name='SuperPlugin',
    version="1.0",
    description="A Super plugin for the 'Baz' project",
    author="Jean Schurger",
    packages=find_packages(),
    include_package_data=True,
    entry_points="""
        [Baz.plugin]
        Foooo=super_plugin:Foo
    "
"",
)

Install your plugin

sudo python setup.py install

Use your plugin

Let's try with ipython

In [1]: from pkg_resources import load_entry_point

In [2]: load_entry_point('SuperPlugin', 'Baz.plugin', 'Foooo')
Out[2]:

In [3]: object = _()
Foo plugin loaded !

In [4]: hasattr(object, "super_function")
Out[4]: True

In [5]: # that's very cool !

In [6]: object.super_function()
Bar !

Just a word about groups and how to discover plugins


In a more complex application, you may have more plugins ! and you may want to
discover them and maybe load them too !
Let's try (with ipython)

In [1]: from pkg_resources import iter_entry_points

In [2]: for object in iter_entry_points(group='Baz.plugin'):
...:     print object
...:
...:
Foooo = super_plugin:Foo

In [3]: object.load()
Out[3]:

In [4]: _().super_function()
Foo plugin loaded !
Bar!

12 juin 2008

HOWTO know if your laptop screen is closed or open ? the desktop way (in python)

Filed under: Code,Python — Jean Schurger @ 3:08
#!/usr/bin/python

import dbus
import dbus.glib
import sys

class LidSwitch(object):
    def __init__(self):

        bus = dbus.SystemBus ()
        hal_obj = bus.get_object ('org.freedesktop.Hal',
                                  '/org/freedesktop/Hal/Manager')
        hal = dbus.Interface (hal_obj, 'org.freedesktop.Hal.Manager')
        udis = hal.FindDeviceByCapability ('input.switch')

        for udi in udis:
            dev_obj = bus.get_object ('org.freedesktop.Hal', udi)
            dev = dbus.Interface (dev_obj, 'org.freedesktop.Hal.Device')
            if dev.GetProperty ('button.type') == "lid":
                self._lid_dev = dev

    def _is_closed(self):
        if hasattr(self, "_lid_dev"):
            return self._lid_dev.GetProperty ('button.state.value')
        else:
            raise ValueError("no lid switch found")

    is_closed = property(_is_closed)

if __name__ == "__main__":
    ls = LidSwitch()
    print "Lid switch is %s" % (ls.is_closed and "closed" or "open")

29 mai 2008

Setup usefull key bindings for metacity with python

Filed under: Code,Python — Jean Schurger @ 3:51

 As you will read the following script configure metacity to let you move your windows to the edges of your screen pressing the keys <Alt> + <Shift> + <the direction key of your choice>

Also it bind <Ctrl> + <Shift> + Up and <Ctrl> + <Shift> + Right to respectivly toggle vertical and horizontal window maximization.

#!/usr/bin/python

from gconf import Client

bindings = dict(
    move_to_side_e='<Alt><Shift>Right',
    move_to_side_w= '<Alt><Shift>Left',
    move_to_side_s= '<Alt><Shift>Down',
    move_to_side_n= '<Alt><Shift>Up',
    maximize_vertically= '<Ctrl><Shift>Up',
    maximize_horizontally= '<Ctrl><Shift>Right')

root = "/apps/metacity/window_keybindings"
c = Client()
for key in bindings.keys():
    c.set_value("%s/%s" % (root, key),
                bindings[key])

Powered by WordPress