Quantcast
Channel: AFPy's Planet
Viewing all 3409 articles
Browse latest View live

[blog.afpy.org] FOSDEM'13

$
0
0

Le week-end dernier a eu lieu le FOSDEM, la rencontre des developeurs open source d'europe. Cette conférence sur l'opensource attire chaque année quelques milliers de "hackers" dans la charmante ville de Bruxelles.

Pour la première fois depuis 2007, une Python devroom était organisée. 16 conférenciers sont venus présenter des sujets allant de Plone à l'analyse de données par la fondation Wikimedia, passant par la découverte d'astuces Pythoniques.

En guise de bonne surprise, la salle était pleine pour bon nombre de conférences et les sujets étaient variés.

http://awesomeness.openphoto.me/custom/201302/fosdem--24-of-29--16dc52_870x870.jpg

La Python devroom, ou comment caser 200 développeurs dans une salle prévue pour 40 personnes (photo par Tarek Ziadé)

Un grand merci à Stéphane Wirtel, Ludovic Gasc, Christophe Simonis et tous les autres organisateurs pour cette formidable journée !

Et on espère bien remettre le couvert l'an prochain !


[Biologeek] Mails et filtres

$
0
0

J'ai un usage du mail qui me semble assez rare pour le détailler ici :

  • je n'archive que très peu de mails : en contrepartie de cela, je conserve l'ensemble des mails que j'envoie (depuis 2006) ce qui me force à conserver la partie nécessaire à la compréhension de ce à quoi je réponds et à être conforme à la Nétiquette ;
  • je n'ai aucun filtre : cela me force à me désabonner de toute liste dont le rapport signal/bruit est trop important et à la plupart des notifications de services tiers, cela me rend indépendant des règles de l'hébergeur ou du client également ;
  • je lis tous les mails reçus : et je réponds souvent dans la semaine, si ma réponse est plus tardive c'est qu'il s'agit d'un mail me demandant plus de réflexion et le correspondant peut s'y attendre, mon inbox comporte en général moins de 10 mails ;
  • je limite mon volume de mails à 1 Go : cela pourrait paraître aberrant vu les espaces de stockage disponibles aujourd'hui mais le coût écologique de ces données n'est pas négligeable, surtout lorsqu'elles sont dupliquées sur chaque périphérique utilisé et sauvegardées en divers endroits.

J'ai mis en place ces pratiques depuis plusieurs années maintenant dans une phase de lâcher-prise qui m'avait amené à ne conserver que mes photos et mes textes sur ma machine, le reste pouvant être (re)trouvé ailleurs à l'occasion. Cette hygiène numérique est la garante de ma propreté intellectuelle.

[hautefeuille] Kivy et sources vidéo sur écrans multiples en OpenGL

$
0
0

Les logiciels qui permettent d’intégrer des flux vidéo de différentes caméras nécessitent souvent une licence.

Aussi je vous propose en guise d’exercice, un prototype d’application capable de visonner 2 flux différents répartis sur des écrans différents.

Un bouton autorise une capture d’image de chaque écran.

Le kit de développement de l’interface graphique se nomme Kivy et propose un affichage OpenGL des informations à traiter. Sa prise en main est rapide et la documentation est abondante.

Kivy.org - http://www.kivy.org

Code de l’application

# -*- coding: utf-8 -*-

"""
@author: julien@hautefeuille.eu

# sudo apt-get install python-kivy

"""
import kivy
kivy.require('1.5.1')

from kivy.app import App
from kivy.uix.widget import Widget
from kivy.uix.camera import Camera
from kivy.uix.video import Video
from kivy.uix.button import Button
from kivy.core.window import Window
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.stacklayout import StackLayout
from kivy.uix.label import Label
from kivy.uix.popup import Popup
from kivy.logger import Logger
from kivy.uix.screenmanager import ScreenManager, Screen

class CamControl(App):

    icon = 'icon.png'
    title = "Cam Control"

    # Callbacks

    def doscreenshot(self,*largs):
        Window.screenshot(name='screenshot%(counter)04d.jpg')
        self.popup.open()

    def next(self,*largs):
        self.sm.current = 'cam2'

    def back(self,*largs):
        self.sm.current = 'cam1'

    def on_start(self):
        Logger.info('Application starts !')

    def on_stop(self):
        Logger.critical('Application quits !')

    # Build UI

    def build(self):

        self.sm = ScreenManager()
        screen1 = Screen(name='cam1')
        screen2 = Screen(name='cam2')

        self.sm.add_widget(screen1)
        self.sm.add_widget(screen2)

        # Create vertical layout
        layout1 = BoxLayout(orientation='vertical', padding=10, spacing=10)
        layout2 = BoxLayout(orientation='vertical', padding=10, spacing=10)

        supralayout1 = BoxLayout(size_hint=(1, .2))
        supralayout2 = BoxLayout(size_hint=(1, .2))

        intralayout1 = BoxLayout(size_hint=(1, .5))
        intralayout2 = BoxLayout(size_hint=(1, .5))

        title_cam1 = Label(text="Cam 1 : Trendnet")
        title_cam2 = Label(text="Cam 2 : Microsoft HD")

        vid = Video(
            source='rtsp://192.168.12.153/mpeg4',
            play=True,
            resolution=(640,480),
            size=(640,480))

        cam=Camera(
             play=True,
             resolution=(640,400),
             size=(640,400))


        content = Label(text='Screenshoot done to current dir !')
        self.popup = Popup(
            content=content,
            auto_dismiss=True,
            title="Info",
            size_hint=(None, None),
            size=(400, 150)
            )
        content.bind(on_press=self.popup.dismiss)

        # Commands
        button1=Button(text="Screenshoot",size_hint=(0.30,0.30))
        button1.bind(on_press=self.doscreenshot)

        button2=Button(text="Screenshoot",size_hint=(0.30,0.30))
        button2.bind(on_press=self.doscreenshot)

        button3=Button(text='Next',size_hint=(0.30,0.30))
        button3.bind(on_press=self.next)

        button4=Button(text='Back',size_hint=(0.30,0.30))
        button4.bind(on_press=self.back)

        # Order is important in vlayout
        layout1.add_widget(supralayout1)
        layout1.add_widget(vid)
        layout1.add_widget(intralayout1)
        supralayout1.add_widget(title_cam1)
        supralayout2.add_widget(title_cam2)
        intralayout1.add_widget(button1)
        intralayout1.add_widget(button3)

        layout2.add_widget(supralayout2)
        layout2.add_widget(cam)
        layout2.add_widget(intralayout2)
        intralayout2.add_widget(button2)
        intralayout2.add_widget(button4)

        screen1.add_widget(layout1)
        screen2.add_widget(layout2)

        return self.sm

if __name__ == ('__main__'):
    CamControl().run()

[Inspyration] Pip : un court tutoriel

$
0
0
Voici un nouveau tutoriel très court sur PIP.

[Inspyration] Quelques réponses sur oursql

$
0
0
Un nouveau tutoriel sur oursql, suite à retour d'expérience

[Biologeek] Le rôle du Product Owner

$
0
0

Quelques notes prises pendant la formation agile/SCRUM donnée par Stéphane ce jour pour scopyleft.

Vision

C'est l'objectif global du produit accessible à toute l'équipe et compréhensible par tout le monde, même et surtout une personne extérieure à l'équipe.

Il est possible de détailler les rôles, la méthodologie ou la technologie dans ce document mais ce n'est pas capital, cela dépend du contexte du produit.

Ce document est relativement bref — surtout au début — pour avoir un ordre d'idée :

  • produit (une page)
  • release (un paragraphe)
  • sprint (une phrase)

La maintenance du document de vision au cours de la vie du produit est très importante.

Réunions

Il y a un cérémonial à respecter qui est représenté par 4 types de rencontres :

  • Planification de sprint (2h) : négociation du backlog avec l'équipe qui hérite symboliquement du produit ;
  • Dailies (15min/jour) : permet de garder le contact et d'annuler l'effet tunnel ; ce que l'équipe a fait, ce qu'elle va faire, les blocages rencontrés (à résoudre par le Scrum Master) ;
  • Démo (1h) : montrer le (totalement) fini, célébrer le travail de l'équipe et réaligner tout le monde, l'équipe rend le produit au product owner ;
  • Rétrospective (1h) : utile pour l'amélioration continue.

Le Product Owner doit être disponible tout au long de la vie du produit.

Il doit également tester les stories terminées pendant le sprint pour faire des retours à l'équipe et s'assurer que les tests d'acceptation sont bien respectés.

Backlog

Chronologie possible des différentes étapes :

  • Inventaire brut des stories
  • Priorisation des stories par valeur métier
  • Rédaction des stories eligibles + tests d'acceptation
  • Challenging des stories avec l'équipe
  • Estimation des stories par l'équipe
  • Re-priorisation possible du backlog par valeur+effort

Stories

Respecter l'acronyme INVEST :

  • Indépendante
  • Négociable
  • Valeur
  • Estimable
  • Small
  • Testable

L'objectif est de maximiser la valeur du projet en minimisant les prédictions.

Une user story est un signal fonctionnel, elle n'est pas détaillée et doit rester flexible. Ce n'est ni une spécification, ni un use-case. Il est possible d'avoir des mockups mais ils sont gardés par la personne qui en a besoin.

Encourager les échanges directs entre le product owner et l'équipe pour résoudre les points flous, en passant parfois par le scrum master.

Schéma de rédaction (peut être simplifié avec l'habitude) :

En tant que {rôle}, je {action} pour apporter {valeur}.

Le curseur de détail des tests d'acceptation peut varier en fonction du besoin, des contraintes du client et de la qualification du product owner.

Ne pas oublier la priorité et l'estimation pour compléter la story. Par exemple, la méthode MoSCoW (MUST, SHOULD, COULD, WON'T) permet de faciliter la priorisation des stories. C'est l'équipe de développement qui découpe les stories en tâches.

L'après-midi a été l'occasion de mettre en pratique la méthodologie sur un sujet concret — celui du client — et d'apporter de la valeur au produit proposé, ce qui s'est soldé par une remise en question très précoce du projet. Les méthodologies agiles permettent de se remettre en question sans avoir rédigé un cahier des charges de plusieurs centaines de pages. Et commencé à le réaliser au prix fort.

[raspberry-python] L'autoréplication

$
0
0

de RaspberryPi a SD


Il y a un certain challenge a faire une carte SD pour le Raspberry Pi.

Ceci est du en partie a la grande variété de systèmes d’opération et d'ordinateurs (et leur matériel). D'autre part, beaucoup de personnes n'ont que le Raspberry Pi comme ordinateur, les autres étant hors de portée du au prix.

Il y a certains groupes d'usagers ici et la qui se débrouillent pour aider les usagers a faire leur propre carte SD, alors que d'autres doivent acheter des cartes SD avec le système d’opération déjà installé. Mais comment faire pour faire une copie de cette carte SD, n'est on pas de retour a la case départ?

Le lecteur


En fait, une fois que l'on a un système d’opération  sur la carte SD, on peut alors faire de l'autoréplication. Quésaco? me direz vous... Et bien, c'est quand un système d’opération peut se répliquer lui même (faire une copie de carte SD seulement avec le Raspberry Pi).

Pour ce faire, il faut un lecteur de carte SD, car le Pi n'a qu'une seule fente SD. Un lecteur comme celui ci, par exemple (ici, avec une carte 16GB, mais on peut faire 4GB ou 8GB ou plus, de la même façon):




Et on le branche (avec un câble ou en direct) au port USB.



dd


La version la plus recente de Raspbian Wheezy est de Decembre 2012:
http://files.velocix.com/c1410/images/raspbian/2012-12-16-wheezy-raspbian/2012-12-16-wheezy-raspbian.zip

Ici, les instructions se basent sur une version plus vieille, mais c'est le meme principe. Il suffit de remplacer l'url http://www.gtlib.gatech.edu/pub/raspberrypi/images/raspbian/2012-09-18-wheezy-raspbian/2012-09-18-wheezy-raspbian.zip par une de cette liste ici (choisir un serveur plus pres de soi): http://downloads.raspberrypi.org/download.php?file=/images/raspbian/2012-12-16-wheezy-raspbian/2012-12-16-wheezy-raspbian.zip


Avant de commencer, il faut s'assurer d'avoir au moins 2.5GB de libre (df -h me donne 2.9G ici). On insere la carte SD vide dans le lecteur et on verra apparaitre /dev/sda ou sdb.



fdion@raspberrypi ~ $ df -h
Filesystem Size Used Avail Use% Mounted on
rootfs 15G 11G 2.9G 80% /
/dev/root 15G 11G 2.9G 80% /
devtmpfs 109M 0 109M 0% /dev
tmpfs 22M 248K 22M 2% /run
tmpfs 5.0M 0 5.0M 0% /run/lock
tmpfs 44M 0 44M 0% /run/shm
/dev/mmcblk0p1 56M 35M 22M 62% /boot
fdion@raspberrypi ~ $ wget http://www.gtlib.gatech.edu/pub/raspberrypi/images/raspbian/2012-09-18-wheezy-raspbian/2012-09-18-wheezy-raspbian.zip
fdion@raspberrypi ~ $ unzip 2012-09-18-wheezy-raspbian.zip
fdion@raspberrypi ~ $ ls /dev/sd*
ls: cannot access /dev/sd*: No such file or directory
fdion@raspberrypi ~ $ ls /dev/sd*
ls: cannot access /dev/sd*: No such file or directory
fdion@raspberrypi ~ $ ls /dev/sd*
/dev/sda /dev/sda1
fdion@raspberrypi ~ $ ls *.img
2012-09-18-wheezy-raspbian.img


Ici, le lecteur de carte avec SD est /dev/sda (si c'est sdb, il faut ajuster la commande ci dessous avec of=/dev/sdb). On est pret a faire la copie de l'image de la carte SD (le fichier .img), a partir du Pi (on peut aussi utiliser bs=4M qui va beaucoup plus vite avec certaines cartes):


fdion@raspberrypi ~ $ sudo dd bs=1M if=2012-09-18-wheezy-raspbian.img of=/dev/sda
1850+0 records in
1850+0 records out
1939865600 bytes (1.9 GB) copied, 428.218 s, 4.5 MB/s
fdion@raspberrypi ~ $ sudo sync


Le sudo sync est très important. Si on ne le fait pas, ça ne fonctionnera pas.

Et c'est tout! On peut maintenant donner cette copie a une autre personne. Tres pratique pour les clubs.

Il existe aussi une méthode pour faire une copie, sans utiliser de fichier .img, mais cela sera pour une autre fois...


François
@f_dion

[Inspyration] oursql : réponse à des problèmes courants

$
0
0
Réponses aux erreurs 2006 mysql has gone away, 2013 Lost connection to MySQL server during query et 2027 malformed packet.

[Inspyration] SQLAlchemy

[Inspyration] Stratégies de chargement

$
0
0
En SQL plus qu'ailleurs, la performance compte. Or, lorsque l'on utilise un ORM, il n'y a rien de plus simple que de mettre une requête dans une boucle sans s'en apercevoir.

[Inspyration] Relations et dépendances

$
0
0
La gestion des relations entre entités SQL est un point important qui n'est pas trivial. Voici quelques bonnes pratiques.

[Inspyration] Reconstruction d'objets

$
0
0
Lorsque l'on utilise des modèles SQLAlchemy, toutes les propriétés ne sont pas stockées en base. Certaines sont construites à la volée. Seulement, l'objet créé de toute pièces et celui récupéré de la base de données ne sont pas initialisés de la même manière. Pour faire les choses proprement, il faut donc recourir à la reconstruction d'objets.

[Inspyration] Polymorphisme

$
0
0
Petite introduction à la gestion du polymorphisme SQL avec SQLAlchemy

[cubicweb] CubicWeb rewarded at Dataconnexion 2013

$
0
0

CubicWeb got rewarded yesterday at the award ceremony of the Dataconnexions 2013 contest.

https://www.cubicweb.org/2710848?vid=download

Dataconnexions is a contest organized by Etalab, the organization part of the French State that is in charge of data.gouv.fr, that catalogs the open data published by the french administration.

Congratulations to all the developers and users of CubicWeb and welcome to the people who will join the CW community thanks to the media coverage we are now experiencing.

Read the announce to the press and the slides.

[Biologeek] Quasynchronicité

$
0
0

Si « la synchronicité est l'occurrence simultanée d'au moins deux événements qui ne présentent pas de lien de causalité » et que « l'asynchronisme désigne le caractère de ce qui ne se passe pas à la même vitesse, que ce soit dans le temps ou dans la vitesse proprement dite », la quasynchronicité est le fait de combiner des événements simultanées dans un temps relativement court sans avoir aucune idée du moment où cela se produit. C'est par exemple ce qui arrive lorsque vous prenez le TGV et comptez sur la connexion 3G/Edge pour pouvoir être connecté à Internet. Vous savez que cela va être possible mais sans savoir quand et vous accumulez un nombre de choses à faire dans ce moment là.

Cela me rappelle les forfaits limités à X heures pour accéder à internet il y a de cela quelques toutes petites années (et la révolution du forfait 50h d'AOL…). Le besoin de regrouper toutes les actions qui nécessitent d'être en ligne pour réduire son temps de connexion.

Cela me rappelle également la notion de contexte dans GTD qui focalise les actions liées bien souvent à un lieu. Et si notre cerveau faisait finalement du DDD ?

La quasynchronicité permet de se focaliser sur la future connectivité tout en l'oubliant parfois l'espace de cet instant. Futile mais indispensable.

Billet rédigé comme il se doit dans un train.


[Biologeek] Opera et Webkit

$
0
0

L'annonce du passage de Presto à Webkit comme moteur de rendu du navigateur Opera représente un tournant du Web. Mais pas celui qui fait réagir les bisounours des standards du Web sur la monoculture Webkit qui était déjà là de fait. Le tournant réside dans l'opposition nord/sud ou plutôt riches/pauvres, car oui Opera était avant tout un navigateur de pauvres. Un navigateur qui permettait à toute une partie de la planète d'avoir accès au Web sur des mobiles jetés par des riches il y a 3/5 ans. Un accès demandant peu de ressources côté client et limitant la consommation de bande passante grâce à une mise en cache agressive. Un navigateur de contenus en somme. En adoptant Webkit, Opera rend définitivement obsolètes tous ces mobiles qui n'auront pas les ressources matérielles pour faire tourner ce nouveau moteur. La chaîne du recyclage propre à l'obsolescence programmée est brisée.

C'est inquiétant pour 2 raisons :

  • Les développeurs web qui testaient déjà rarement le rendu sous Presto ne vont même plus en avoir les moyens et rapidement les sites ne vont plus être consultables avec ce moteur ; ce qui va priver momentanément une partie de la population d'un accès au savoir et à la culture. Celle qui en a le plus besoin.
  • Si Opera a fait ce choix stratégique, cela signifie qu'il y a peu de sites développés par les pauvres et pour les pauvres. C'est terrible en termes de partage culturel et d'éducation. On se retrouve dans une situation où la seule connaissance diffusée sur le Web est occidentale, la seule éducation prodiguée est dictée par des riches.

Le risque n'est pas une monoculture Webkit mais une monoculture occidentale. De riches. Si seulement on pouvait avoir une presse informatique qui creuse un peu tout ça…

[Inspyration] Quelques modules intéressants

$
0
0
Présentation de quelques modules intéressants à tester, voire adopter.

[tarek] Fun with AngularJS & Cornice

$
0
0
http://blog.ziade.org/dashboard.png

I blogged about it a few weeks ago: in my opinion, we're moving to an ecosystem where our web applications are built of JSON web services and of Javascript applications that use those services to fetch data and display them.

In other words, server-side templating is fading away and client-side templating based on frameworks like AngularJs is getting a lot of traction.

As a Python developer in the Mozilla Services team, one tool that is starting to play an important role is Cornice, because it's the perfect companion for building a Javascript application.

Cornice features that are really useful in this context:

  • CORS support
  • based on a robust & mature framework: Pyramid
  • dead-simple Mozilla Persona integration, thanks to a vibrant Pyramid ecosystem
  • standard machine-parseable errors
  • can run everything in async mode

Busting the myth about Python & async programming

Before I talk about the topic, I want to make a little digression and bust a myth about Python vs Javascript.

I have heard this sentence several times in Javascript and Node.js developers circles:

Python doesn't support async programming

I've even heard some people explaining that Python couldn't be used as an async language because of the GIL !

Talking about the GIL in this context is completely out of topic. Like Python, Javascript has something similar to the GIL (locks in "Isolates" in V8). But the GIL becomes an issue only when you run several threads in the same process.

And in web programming, we don't really use threads anymore.

Node.js is single-threaded and uses libuv to run an event loop, and feeds the loop with callbacks.

Python has also libraries and frameworks that provide event loops. In fact, Node.js was inspired by Twisted.

There are libuv, libevent & libev bindings in Python. And frameworks and libraries that use those bindings to provide event loops.

That said, I am not a huge fan of callback programming, I find it quite hard to read and debug. I like it better when I am working with thread-like objects.

Fortunately in Python we have gevent that will provide greenlets, which are pseudo-threads that wrap callbacks and an event loop - and you don't have to do callbacks anymore.

Gevent takes care of the gory details and let you do linear, functional programming that can be traced, debugged, without falling into an horrible maze of callbacks.

A code like this...

# from https://github.com/SiteSupport/gevent/blob/master/examples/concurrent_download.py
import gevent
from gevent import monkey
monkey.patch_all()

import urllib2

urls = ['http://www.google.com', 'http://www.yandex.ru', 'http://www.python.org']

def print_head(url):
    print ('Starting %s' % url)
    data = urllib2.urlopen(url).read()
    print ('%s: %s bytes: %r' % (url, len(data), data[:50]))

jobs = [gevent.spawn(print_head, url) for url in urls]

gevent.wait(jobs)

...will asynchronously download all URL pages, and let you work with greenlets.

Some people don't like this approach and use tools like Tornado, that will let you start an event loop and define callbacks, like Node.js.

But enough said - my point is made:

Yes, the Python ecosystem has the same tools than the Javascript/Node.js ecosystem to do async programming. And it has much more to offer in fact.

Cornice for the JSON APIs

For the Marketplace, we're working on building a separated application to provide a metrics dashboard.

The goal is to display interactive dashboards filled with some Highcharts based charts.

The primary goal is to replace the ones we have in the Marketplace application, that give to the users info like the number of downloads for their web apps.

For this, we're going to provide a set of JSON APIs on the top of an Elastic Search server, using Cornice.

Cornice acts as a proxy in front of the Elastic Search server, but also provides a few extra APIs and features we need - it also integrates the excellent pyelasticsearch library.

To give you an idea of how hard is to build such an application with Cornice, here's the core of the code:

es = Service(name='elasticsearch', path='/es')

@es.post(validators=(valid_json_body,), renderer='json')
def query_es_time(request):
    try:
        return request.es.search(request.validated['body'], index='time_*')
    except ElasticHttpError as e:
        request.response.status = e.status_code
        return e.error

The Service class provided by Cornice does a lot of automation here, like sending back a clean JSON error message in case the query is malformed. It also checks that we don't return a JSON list - since that can be a security hole. It makes sure the server returns a 405 if it's called with the wrong method, etc.

You get the idea: Cornice takes care of the things we never think about, and don't want to think about.

AngularJS for the client-side

I tried out Ember.js and quickly disliked the way the templating works in it, and the fact that they define objects for every element you want to add in the DOM.

Cedric gave a more detailed comparison of Ember vs Angular, and I really liked how Angular looked, so I gave it a shot and instantly liked it.

Angular will let you define new DOM directives, that get expanded on the client side at runtime.

For the dashboard, it means I can define something like this:

<dasboard server="http://data.marketplace.mozilla.org/">
    <chart title="Downloads" type="series" field="downloads_count"/>
</dashboard>

And have a nice Highchart dashboard that grabs data out of the Cornice server that's behind http://data.marketplace.mozilla.org (Fake URL!)

Defining directives in Angular is done by providing an HTML template and a bit of Javascript glue code.

In our case we also make the chart directive a sub-directive of the dashboard directive - here's an extract of the code so you get an idea:

var app = angular.module('components', []);

app.directive('dashboard', function() {
    return {
        restrict: 'E',
    scope: {},
    transclude: true,
    controller: function($scope, $element, $attrs) {
        this.server = $scope.server = $attrs.server;
        var charts = $scope.charts = [];
        this.addChart = function(chart) {
            charts.push(chart);
        }
    },
    template:
    '<div class="tabbable">' +
    '<h3>Monolith Dashboard</h3>' +
    '<div class="tab-content" ng-transclude></div>' +
    '</div>',
    replace: true
    };
});

Full code: https://github.com/mozilla/monolith/blob/master/monolith/media/app.js#L30

What I like about Angular is that it's easy to build something that's based on a collection of Plain Old Javascript Objects, so I actually made a separate library that takes care of creating a chart and interacting with the server and the user, given a few tags ids: https://github.com/mozilla/monolith/blob/master/monolith/media/lib/monolith.js#L194

On testing Javascript

I had no idea what was the state of the art for testing Javascript applications since I am a backend developer, so I used what the Angular.js team use and partially built: Testacular & Jasmine.

Testacular is a nice command-line too that will spawn a Firefox instance and run your tests in it. It has nice features like auto-running when a JS file changes, and you can remote-controll it because it uses a Node.JS server to provide interactions.

Although, one thing that annoys me in Javascript (as opposed to Python), is the fact that it's not easy to run processes in your tests fixtures.

What I needed to do is:

  • run an Elastic Search server & add content in it
  • run the Monolith Server
  • then, run the JS tests.

In Python-land, all of this can happen in your test classes. In Javascript, unless I missed the obvious, I had to wrap it in a Makefile: https://github.com/mozilla/monolith/blob/master/Makefile#L30

It's still a bit clunky because I cannot garantee the two servers are really stopped. I should do something better. Maybe I'll end-up wrapping testacular in a Python unit tests... :)

Overall, I quite like building this kind of applications - and I think this pattern of having a light Python web service on the server side, and some kind of JS MVC-based tool on the client-side, is soon going to be the norm.

[logilab] FOSDEM 2013

$
0
0

I was in Bruxelles for FOSDEM 2013. As with previous FOSDEM there were too many interesting talks and people to see. Here is a summary of what I saw:

In the Mozilla's room:

  1. The html5 pdf viewer pdfjs is impressive. The PDF specification is really scary but this full featured "native" viewer is able to renders most of it with very good performance. Have a look at the pdfjs demo!
  1. Firefox debug tools overview with a specific focus of Firefox OS emulator in your browser.
  1. Introduction to webl10n: an internationalization format and library used in Firefox OS. A successful mix that results in a format that is idiot-proof enough for a duck to use, that relies on Unicode specifications to handle complex pluralization rules and that allows cascading translation definitions.
typical webl10n user
  1. Status of html5 video and audio support in Firefox. The topic looks like a real headache but the team seems to be doing really well. Special mention for the reverse demo effect: The speaker expected some format to be still unsupported but someone else apparently implemented them over night.
  2. Last but not least I gave a talk about the changeset evolution concept that I'm putting in Mercurial. Thanks goes to Feth for asking me his not-scripted-at-all-questions during this talk.
http://www.selenic.com/hg-logo/logo-droplets-150.png

In the postgresql room:

  1. Insightful talk about more event trigger in postgresql engine and how this may becomes the perfect way to break your system.
  2. Full update of the capability of postgis 2.0. The postgis suite was already impressive for storing and querying 2D data, but it now have impressive capability regarding 3D data.
http://upload.wikimedia.org/wikipedia/en/6/60/PostGIS_logo.png

On python related topic:

http://www.python.org/community/logos/python-logo-master-v3-TM-flattened.png
  • Victor Stinner has started an interesting project to improve CPython performance. The first one: astoptimizer breaks some of the language semantics to apply optimisation on compiling to byte code (lookup caching, constant folding,…). The other, registervm is a full redefinition of how the interpreter handles reference in byte code.

After the FOSDEM, I crossed the channel to attend a Mercurial sprint in London. Expect more on this topic soon.

[raspberry-python] Audio numerique sur RaspberryPi

$
0
0

Audiophile

Pour que le Raspberry Pi coute le moins possible, certaines décisions on du être prise. Par exemple, il n'y a pas de CODEC analogique - numérique. De sorte que l'audio se joue par soit:

1) le port HDMI - audio numérique passée directement au téléviseur ou a l'ampli intégré avec décodeur DTS, dolby digital, master audio etc... Si on utilise le Raspberry Pi comme serveur de media, c'est parfait. Mais si on ne peut utiliser le port HDMI?

2) le port 3.5mm analogique - l'audio est générée par PWM (Pulse Width Modulation). Avec une fréquence suffisamment élevée, on peut arriver a 16 bit de résolution, comme les convertisseurs plus conventionnels. Dans le cas du Raspberry Pi toutefois, la résolution est un peu moindre. En plus, il y a un problème avec le pilote ALSA, de sorte que le son n'est pas vraiment... a la hauteur.

USB

Tout n'est pas perdu. En effet, on peut se procurer une carte son sur USB:
Mini PCM2704 USB sur ebay (A noter que le prix est a la hausse, de $4.00 par rapport a ce que j'ai payé ...).

C'est géré par le Raspberry Pi: 

$ lsusb
Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
Bus 001 Device 002: ID 0424:9512 Standard Microsystems Corp.
Bus 001 Device 003: ID 0424:ec00 Standard Microsystems Corp.
Bus 001 Device 004: ID 08bb:2704 Texas Instruments Japan

Et ça donne une sortie analogique 3.5mm de qualité (super sur casque d’écoute), une sortie SPDIF rca numérique et une TOSLink optique numérique.
de USB a SPDIF, TOSLink et 3.5mm analogique

Illusion d'optique

Dans mon cas, je saute le DAC. J'utilise la carte son comme interface numérique optique, qui se relie a un processeur de son numérique Technics SH-AC500D (qui lui se branche a un ampli):

Le processeur de son est sur le dessus

La lumiere au bout ... de la fibre
On branche la fibre sur un des ports TOSlinks

Le soft


mpg123, aplay et d'autres lecteurs audio qui utilisent ALSA vont fonctionner avec la carte, mais il faut effectuer un changement a un fichier de configuration:

$ sudo vi /etc/modprobe.d/alsa-base.conf

et sur la derniere ligne, on change le -2 par un 1:

options snd-usb-audio index=-2
devient
options snd-usb-audio index=0 nrpacks=1
et on reboot.

François
@f_dion
Viewing all 3409 articles
Browse latest View live