Planète AFPy RSS

[afpyro] AFPyro à Mons (BE) - le 2 Octobre

Publié le 2014-10-02 00:00:00

English version at the end of this page.

Amis Pythonistes, notez la date du prochain AFPyro (et venez-y) !

Le prochain Apero Python Belgium se tiendra le jeudi 2 Octobre à Mons, lors de la Quizaine Numérique de Mons, du 27 septembre au 19 octobre.

En plus des habitués de l’AFPyro, nous accueillerons des débutants en Python afin de leur présenter la puissance du langage.

Vous pourrez ainsi participer à un des deux workshops proposés en parallèle :

  1. Pour les Pythonistes débutants, un workshop pour apprendre les bases de Python, puis pour construire une application Web avec Flask.

2. Pour les développeurs avancés, une initiation à AsyncIO, suivie d’un exemple concret d’une API REST/JSON asynchrone avec AsyncIO, aiohttp, aiorest et aiopg. Enfin, un benchmark sera réalisé afin de comparer les performances avec une API REST/JSON synchrone en Flask.

N’oubliez pas de prendre votre ordinateur portable si vous voulez participer au workshop.

Bien entendu (car c’est dans le nom), un apéro sera également organisé pendant l’événement.

Rendez-vous à partir de 18h30, à Co-nnexion, Espace de Coworking, 2b Rue des Archers, 7000 Mons.

Toutes les infos des prochains AFPyros en Belgique : Aperos Python Belgium


Dear Pythonista friends, write down in your agenda the date of the next AFPyro (and come to it) !

The next Aperos Python Belgium will take place on Thursday, October 2nd in Mons, during the Quizaine Numérique de Mons.

Not only the regulars of AFPyro are welcome. We are also pleased to meet the beginners who want learn Python.

Two workshops will be available:

  1. For the Python beginners, a workshop to learn Python basic, then to build a Web application with Flask.

2. For the advanced developers, a workshop around AsyncIO with a REST/JSON API example with AsyncIO, aiohttp, aiorest et aiopg. Finally, a benchmark will be made to compare performances with a synchronous REST/JSON API with Flask.

Don’t forget your laptop if you want to take part of a workshop.

Of course (it’s in the name), an “apéro” will be also organized throughout the event.

Meeting as from 18:30, at Co-nnexion, Espace de Coworking, 2b Rue des Archers, 7000 Mons.

Further informations about the next AFPyros in Belgium: Aperos Python Belgium

[hautefeuille] RaspberryPI, NAS Synology et NFS

Publié le 2014-10-01 15:13:00

Introduction

L’objectif de ce billet est d’installer le système de fichiers Raspbian sur un répertoire partagé d’un NAS Synology par l’intermédiaire du protocole NFS.

Cette installation permet de soulager la carte mémoire. Celle-ci n’est en fait nécessaire que pour le démarrage de la carte RaspberryPI.

Prérequis

Il faut disposer d’une carte mémoire avec le système Raspbian déjà installé et configuré. Internet regorge de tutoriels sur l’installation de Raspbian.

L’adresse ip du serveur NAS est 192.168.0.3, l’adresse ip de la carte RaspberryPI est 192.168.0.199.

Il faut disposer d’un réseau local rapide car les fichiers du sytème de la RaspberryPI transiteront par le réseau.

J’ai également pu remarquer des problèmes de connection NFS lorsqu’une MTU trop élevée était utilisée.

Je n’utilise donc pas les “Jumbo frame” dans la configuration réseau du NAS Synology.

MTU

Préparation du NAS Synology

On crée tout d’abord un répertoire partagé.

share

On autorise ensuite le partage par NFS, sans mapping, en lecture / écriture. Le dossier exporté par NFS est donc le suivant : /volume1/rasp0.

share

192.168.0.199 correspond à l’adresse ip de la carte RaspberryPI.

Préparation de la carte mémoire

Dans un premier temps, nous allons monter le partage réseau NFS sur la carte RaspberryPI puis nous allons copier le système de fichiers sur cet emplacement réseau.

sudo mount -t nfs -o rw 192.168.0.3:/volume1/rasp0 /mnt
cp -axv /. /mnt/.
cp -axv /dev/. /mnt/dev/.

Préparation des fichiers du partage réseau

On édite ensuite le fstab du partage réseau auquel on ôte le point de montage de la carte mémoire, ici il s’agit de /dev/mmcblk0p2.

proc            /proc           proc    defaults 0 0
/dev/mmcblk0p1  /boot           vfat    defaults 0 0
none            /tmp            tmpfs   defaults 0 0
none            /var/run        tmpfs   defaults 0 0
none            /var/lock       tmpfs   defaults 0 0
none            /var/tmp        tmpfs   defaults 0 0
192.168.0.3:/volume1/rasp0  /   nfs     rw       0 0

La dernière ligne de la configuration est facultative puisqu’on va renseigner également cette information dans le fichier de boot dans la suite de ce billet.

On édite le fichier /etc/network/interfaces du partage réseau pour y désactiver toute référence à du DHCP.

#iface eth0 inet dhcp

Préparation de la séquence de boot (fichier sur la carte mémoire)

On édite le fichier de la carte mémoire /boot/cmdline.txt.

On y ajoute des informations complémentaires sur la même ligne que la ligne d’origine. Si vous êtes en DHCP, mettez ip=dhcp.

root=/dev/nfs rootfstype=nfs nfsroot=192.168.0.3:/volume1/rasp0,udp,vers=3 smsc95xx.turbo_mode=N ip=192.168.0.199:192.168.0.3:192.168.0.1:255.255.255.0
  • 192.168.0.199 est l’adresse de la carte RaspberryPI,
  • 192.168.0.3 est l’adresse du NAS Synology avec le partage NFS,
  • 192.168.0.1 est l’adresse de la passerelle,
  • 255.255.255.0 est le masque réseau.

Vous pouvez enfin rebooter la carte RaspberryPI.

Optimisations

Enfin pour soulager la carte mémoire, nous allons bouger la swap de la carte mémoire vers un loop device à travers le réseau.

sudo apt-get remove --purge dphys-swapfile
sudo rm /var/swap
sudo rm /etc/init.d/dphys-swapfile
sudo update-rc.d dphys-swapfile remove

sudo dd if=/dev/zero of=/var/swap bs=1M count=1024
sudo losetup /dev/loop0 /var/swap
sudo mkswap /dev/loop0
sudo swapon /dev/loop0

On édite ensuite /etc/rc.local du partage réseau pour y rendre les changements permanents.

echo "swap settings"
sleep 2
losetup /dev/loop0 /var/swap
mkswap /dev/loop0
swapon /dev/loop0

Liens

[anybox] Sphinx autodoc et modules OpenERP

Publié le 2014-10-01 01:00:00
Guide d'intégration complète d'OpenERP et Sphinx, pour les utilisateurs de buildout.

[Biologeek] 10 ans

Publié le 2014-09-30 11:00:00

C’est difficile à décrire la naissance d’un site, ce qu’on voulait faire, ce que l’on a finalement fait, les doutes, les satisfactions, l’incompréhension de certains, les encouragement d’autres, parfois les mêmes d’ailleurs (normal c’était une surprise). Et le résultat est là, sous vos yeux ébahis : merci à vous, visiteur !

Ouverture de rideau, 30 septembre 2004

Dix années de présence, plus ou moins régulière, plus ou moins pérenne. C’est passé par de la bio-informatique, la création d’ubuntu-fr, la découverte de Python, des réflexions sur la liberté, des essais en CSS, des billets personnels, de l’énergie avec django-fr, des coups de gueule, le grand saut en freelance, quelques photos, un peu de sport, du web sémantique, le montage d’événements, une année au Japon, la co-création de scopyleft, de la philo de comptoir et enfin la paternité. Plein de projets avortés, pas mal de discussions stériles, des rencontres toujours un peu spéciales, des rides numériques partagées. Dix années à tisser ma propre toile. Des liens sans intentions, par affinités au hasard des rencontres. Une audience suffisamment limitée pour ne pas prendre la grosse tête ou être dérangé dans mon intimité.

Cet espace de publication m’aura tout appris de mon métier : l’importance des données et de leurs liens. Je l’ai appris dans la douleur : le design a changé 6 fois, les URLs 5 fois, les données 4 fois, le nom de domaine 1 fois. Ce lieu m’a permis d’expérimenter et de prendre du plaisir à ça, d’être corrigé et de capitaliser itérativement. J’ai offert un cadeau à mes écrits dernièrement en utilisant les polices Fira Sans et Equity afin de vous préserver des mouchards d’Adobe/Typekit (et le gain niveau performances est impressionnant). J’ai d’ailleurs rafraichit un peu tout ça, en utilisant TinyTypo et LESS. Je voulais notamment mettre en avant les citations qui débutent les billets, ça reste très minimaliste pour l’instant et il reste les finitions.

Et pour ces 10 prochaines années ? Peut-être du son, peut-être de la vidéo, peut-être du papier, peut-être la page blanche. J’espère avoir toujours de l’énergie pour explorer et partager de nouveaux centres d’intérêts. Avec vous ?

[logilab] Lancement du blog de la communauté salt francaise

Publié le 2014-09-25 16:14:00

La communauté salt est bien vivante. Suite au meetup de septembre, elle s'est doté d'un petit site web :

http://salt-fr.afpy.org
http://www.logilab.org/file/266455/raw/Screenshot%20from%202014-09-25%2014%3A32%3A27.png

Nous éspérons pouvoir continuer à rassembler les enthousiasmes autour de salt lors de ces rendez-vous tous les 2 mois. J'ai donc publié le compte rendu du meetup sur ce site.

[afpyro] AFPyro à Lyon - mercredi 24 septembre

Publié le 2014-09-24 00:00:00

Un Afpyro aura lieu le mercredi 24 septembre à partir de 19h à l’Antre Autre - 11 rue Terme - 69001 Lyon.

Une présentation sur les docstrings sera donnée au cours de cette soirée.

L’Antre Autre est un lieu où nous pouvons discuter autour d’un verre, et, pour ceux qui le souhaitent, prendre un repas.

Pour se rendre à l’Antre Autre :

  • en métro : arrêt Hôtel de Ville
  • en bus : lignes C13 et C18 arrêt Mairie du 1er ou lignes 19, C14 et C3 à l’arrêt Terreaux
  • en vélo’v : stations Place Sathonay, Carmélites Burdeau, Place de la paix

[cubicweb] Handling dependencies between form fields in CubicWeb

Publié le 2014-09-17 15:50:00

This post considers the issue of building an edition form of a CubicWeb entity with dependencies on its fields. It's a quite common issue that needs to be handled client-side, based on user interaction.

Consider the following example schema:

from yams.buildobjs import EntityType, RelationDefinition, String, SubjectRelation
from cubicweb.schema import RQLConstraint

_ = unicode

class Country(EntityType):
    name = String(required=True)

class City(EntityType):
    name = String(required=True)

class in_country(RelationDefinition):
    subject = 'City'
    object = 'Country'
    cardinality = '1*'

class Citizen(EntityType):
    name = String(required=True)
    country = SubjectRelation('Country', cardinality='1*',
                              description=_('country the citizen lives in'))
    city = SubjectRelation('City', cardinality='1*',
                           constraints=[
                               RQLConstraint('S country C, O in_country C')],
                           description=_('city the citizen lives in'))

The main entity of interest is Citizen which has two relation definitions towards Country and City. Then, a City is bound to a Country through the in_country relation definition.

In the automatic edition form of Citizen entities, we would like to restrict the choices of cities depending on the selected Country, to be determined from the value of the country field. (In other words, we'd like the constraint on city relation defined above to be fulfilled during form rendering, not just validation.) Typically, in the image below, cities not in Italy should be available in the city select widget:

Example of Citizen entity edition form.

The issue will be solved by little customization of the automatic entity form, some uicfg rules and a bit of Javascript. In the following, the country field will be referred to as the master field whereas the city field as the dependent field.

So here the code of the views.py module:

from cubicweb.predicates import is_instance
from cubicweb.web.views import autoform, uicfg
from cubicweb.uilib import js

_ = unicode


class CitizenAutoForm(autoform.AutomaticEntityForm):
    """Citizen autoform handling dependencies between Country/City form fields
    """
    __select__ = is_instance('Citizen')

    needs_js = autoform.AutomaticEntityForm.needs_js + ('cubes.demo.js', )

    def render(self, *args, **kwargs):
        master_domid = self.field_by_name('country', 'subject').dom_id(self)
        dependent_domid = self.field_by_name('city', 'subject').dom_id(self)
        self._cw.add_onload(js.cw.cubes.demo.initDependentFormField(
            master_domid, dependent_domid))
        super(CitizenAutoForm, self).render(*args, **kwargs)


def city_choice(form, field):
    """Vocabulary function grouping city choices by country."""
    req = form._cw
    vocab = [(req._('<unspecified>'), '')]
    for eid, name in req.execute('Any X,N WHERE X is Country, X name N'):
        rset = req.execute('Any N,E ORDERBY N WHERE'
                           ' X name N, X eid E, X in_country C, C eid %(c)s',
                           {'c': eid})
        if rset:
            # 'optgroup' tag.
            oattrs = {'id': 'country_%s' % eid}
            vocab.append((name, None, oattrs))
            for label, value in rset.rows:
                # 'option' tag.
                vocab.append((label, str(value)))
    return vocab


uicfg.autoform_field_kwargs.tag_subject_of(('Citizen', 'city', '*'),
                                           {'choices': city_choice, 'sort': False})

The first thing (reading from the bottom of the file) is that we've added a choices function on city relation of the Citizen automatic entity form via uicfg. This function city_choice essentially generates the HTML content of the field value by grouping available cities by respective country through the addition of some optgroup tags.

Then, we've overridden the automatic entity form for Citizen entity type by essentially calling a piece of Javascript code fed with the DOM ids of the master and dependent fields. Fields are retrieved by their name (field_by_name method) and respective id using the dom_id method.

Now the Javascript part of the picture:

cw.cubes.demo = {
    // Initialize the dependent form field select and bind update event on
    // change on the master select.
    initDependentFormField: function(master_select_id,
                                     dependent_select_id) {
        var master_select = cw.jqNode(master_select_id);
        cw.cubes.demo.updateDependentFormField(master_select, dependent_select_id);
        master_select.change(function(){
            cw.cubes.demo.updateDependentFormField(this, dependent_select_id);
        });
    },

    // Update the dependent form field select.
    updateDependentFormField: function(master_select,
                                       dependent_select_id) {
        // Clear previously selected value.
        var dependent_select = cw.jqNode(dependent_select_id);
        $(dependent_select).val('');
        // Hide all optgroups.
        $(dependent_select).find('optgroup').hide();
        // But the one corresponding to the master select.
        $('#country_' + $(master_select).val()).show();
    }
}

It consists of two functions. The initDependentFormField is called during form rendering and it essentially bind the second function updateDependentFormField to the change event of the master select field. The latter "update" function retrieves the dependent select field, hides all optgroup nodes (i.e. the whole content of the select widget) and then only shows dependent options that match with selected master option, identified by a custom country_<eid> set by the vocabulary function above.

[AFPy-Nantes] Un barcamp pour bien terminer l'été indien

Publié le 2014-09-14 22:00:00

Suite au succès du dernier meetup, et pour bien finir ce mois de septembre ensoleillé, nous sommes heureux de vous proposer un nouveau BarCamp, le mardi 30 septembre, 19 heure, à la Cantine numérique Nantaise.

Le concept sera de se retrouver autour de plusieurs ateliers, et de participer collectivement, chacun étant invité à présenter ses trouvailles, à poser ses questions, etc.

Que vous soyez pythoniste confirmé, ou simple curieux, le format du barcamp devrait donc répondre à vos attentes : la découverte, l'échange, le collaboratif.

Comme d'habitude, ceux qui le souhaitent pourront prolonger l'évènement autour d'un verre.

Pour vous inscrire à l'évènement, cliquez ici.

Pour vous tenir informé du contenu exact de l'évènement, ou pour faire part de vos suggestions, n'hésitez pas à vous inscrire à la liste de diffusion des pythonistes nantais.

Vous pouvez aussi nous rejoindre sur le chan IRC de l'AFPy Nantes. :)

[tarek] The Perfect Running App

Publié le 2014-09-14 17:05:00

Note

Most running applications out there are good enough for casual runners. This blog post is my tentative to describe what I would like to see in a running app for more serious practice.

I used a few running applications to track all my runs. Mostly the Nike+ app since this what naturally came with my Nike+ watch before I switched to a Garmin Forerunner 310XT.

Changing watch

From Nike+ to Garmin...

The app was a bit frustrating for many reasons and I thought that was because it's made for beginners, and that I was not the typical user anymore. I was not really interested in the provided metrics and was looking for better things.

When I switched to my new watch I though the app would be as good as the hardware. But no. What came as a surprise is that all the applications I have tried or looked at are not really better than Nike+. It looks like they are all aiming at casual runners.

But when you buy a expensive watch and do 5 trainings per week, you have some expectations.

I still wonder how come we don't have something better in a domain where anyone can understand the basics of what a good training session should be, by reading 2 or 3 running magazines. Unless you are doing crazy elite training with a whole staff, it's not rocket science.

And in my running club, even the very experienced runners use one of these apps and get frustrated. But it seems that no one expects these apps to be better than they are right now. The general consensus around me is: you can analyze your runs manually, the watch and its software will just help you get the raw data.

This is not good enough for me. I am very frustrated. I want to see if I am making any progress by using months of data - and this is not easy to do by hand.

SmashRun looks like a promising app but still misses a lot of what I am looking for. Since it's built by runners who seem passionate about building the right stuff, I got a pro account to encourage them. They have a voting system for new features, people that have a pro account can use.

However, I would like to write down in this blog post what I am exactly looking for and what I despise in a running app.

Of course this is what I want - but I am pretty sure that most seasoned runners would want something similar. Maybe it exists ? You should let me know.

Stop comparing Apples and Oranges

I think this is the worst feature all running apps have: they will tell you your average pace and your "progression". Some of them try to take a coach-like tone and tell you stuff like:

You're getting slow!

Jeez. Of course I am getting slow. I ran an interval run yesterday with a specific pace of 3'40/km and today I am doing a long run at a very slow pace because this is how you train !

pace over the week

Yeah the pace varies during the week. Nothing I can do with this chart here.

Global metrics that use all your recorded runs have no sense

You can't do this. That does not mean anything. Knowing that my yearly average pace is 4'45 does not mean anything.

You can't either really know what will be my estimate finish on a 5k using one of my long runs.

Performance Index

My estimated 5k finish time based on one long run. Of course it's completely wrong.

Also, the volume of trainings and kilometers you do really depends on what you're aiming at. Someone that is getting ready for a marathon will do at least 60km/week, and will take it easy the last week.

That would be a non-sense if you are getting ready for a 5k - But in most apps, the runner that prepares for the marathon will appear like a killer compared to the 5k runner. Tell this to the runners that are doing 16' on a 5k...

Gold Medal

I will soon lose my Gold medal since my 5 weeks training plan is over.

Anyways. My point is that the software should be smarter there. Every run needs to be classified in very specific groups to have any useful metrics on it. The most important ones are:

  • long runs
  • short interval runs
  • long interval runs
  • races

Long Runs

A long run is basically running at a lower pace for a longer time than usual. If you are getting ready for a 10k, you usually have one or two long runs per week, that will last for 1h to 1h30 tops.

The goal of those runs is to try to keep the same steady heart rate, and usually if the place where you are running is flat enough, the same pace.

A long run look like this:

Long run

The red zone is the HR drift.

There are several interesting things in this chart: you don't usually warmup when you do long runs. So the first portion of the run is a slow raise of your pace and heart rate until you've reached the targeted zone.

The quality of a long run is your ability to stick with the same heart rate for the whole session. Unless you are very careful and slow down a bit over time, there will be a slow, natural increase of your heart reate over time.

The most interesting metric in the case of a long run is to determine how flat your HR is, excluding the warmup section at the beginning.

A possible variation is to add a few strikes in the middle of your long runs. It makes it less boring. For example 2x2mn at 10k speed. It's important that these two strikes don't confuse the software that measures how flat your HR is.

Comparing long runs can be done by looking at;

  • how good you are at keeping the desired HR over time
  • how fast your heart is beating for a given pace as long as the circuit is flat enough and how this evolves over time.

Short Interval Run

If I do a short interval run, this is how things will go:

  • 30' warmup
  • 12x (45" at max speed, 30" slow)
  • 10' to cool down
Long run

The red line is the linear regression of the fast strikes.

We can ditch the warmup. It does not bring any interesting data besides the volume of training. The only interesting thing to do there is to make sure it was long enough. That varies between runners, but for short intervals, it's usually roughly as long as the intervals themselves.

Now for the intervals, a quality metrics is to check if they are all done at the same speed. It's quite common to start the series very fast and to finish slowly, completely burnt by the first strikes. This is not good! A good interval run is done at the same speed for all strikes (both fast and slow segments). A great interval run is done with a slightly faster speed for the last intervals.

A good metrics in this case is the linear regression of the pace for the fast segments then the slow segments. It should be flat or slightly increasing.

The ten last minutes are also very intesting: how fast your heart rate decreases over the ten minutes ? The faster the better.

Comparing interval runs between them can be done by checking how these metrics progress over time.

Long Interval Runs

Long interval runs are like the short ones. The only difference is that you can take into account your HR variation between strikes to see how good you are at decreasing your HR between each strike. A linear regression can be added there.

Race

A Race is a very specific run, and has its specific metrics. Usually, we tend to start too fast with the danger of getting in the red zone in the first kilometers.

This is the perfect 10k run:

Long run

A 10K run with a perfect negative split.

The first 5-6k are down 3-5 seconds slower than your target pace, and the end of the run 3-5 seconds faster. This is called a negative split. The last 500m should be as fast as you can.

So for races, what I want to find out is if I was able to do a negative split, if I did not start too fast and if I was able to sprint to the finish line.

This is also a set of metrics that can be compared from race to race over time.

The Impact of Temperature

I have a friend at the racing club that trained hard for 8 weeks for a marathon. He was aiming at 3h15mn and practiced accordingly. The day the race was there, we had a very unusual heat wave in France - 37ºC which is a lot for my area. He finished the marathon in 3h40 and was happy about his performance!

The bottom line is that the heat or the cold directly impact how we perform - and this varies a lot between individuals. In my dream running app, I want to correlate my results with the temperature.

I want all my predictions to have a ponderation (not sure that's how you say it in english ;)) with the temperature.

The Impact of Rest

How long did you rest since the last run ? How did it impact your performances ?

With this information and how fast your heart slows down after your training, we can detect overtraining and undertraining.

I know Polar has a bit of this in its latest software. It tells you how long you should rest before your next run. I wonder how they calculate this.

The Social Part

Last year I ran in San Franscisco near the bay bridge with my Nike+ watch and when I uploaded my run I was delighted to see that I did a 1 mile segment many people did.

Unfortunately, the only thing the app was able to tell me is that I was 365th in terms of pace and another ridiculous rank in terms of how many runs I did there.

This is so stupid. Where am I getting with this ? Becoming the Running Mayor of the Pier? :)

There's one thing that could be interesting in running apps when comparing your data with other people: group users by ages and by records.

I am 37 and my 10k record is around 38' - I don't really care to know how I perform on a weekly basis compared to an elite runner who does 31', or a more casual runner who does 50'.

What could be interesting though is to compare with people that are at my level or age and that are getting ready for the same race maybe ? or a race that's similar enough and close enough.

Conclusion

This blog post is just a brain dump - some ideas are pretty vague and I have not really talked about the UX of the Running Software.

But the bottom line is that if you don't just jog, and want to use a running application for serious training, what I have described is what I think is needed.

I hope Smashrun will go into that direction!

[cubicweb] CubicWeb roadmap meeting on September 4th, 2014

Publié le 2014-09-08 23:52:00

The Logilab team holds a roadmap meeting every two months to plan its CubicWeb development effort. The previous roadmap meeting was in July 2014.

Here is the report about the September 4th, 2014 meeting. Christophe de Vienne (Unlish) and Dimitri Papadopoulos (CEA) joined us to express their concerns and discuss the future of CubicWeb.

Versions

Version 3.17

This version is stable but old and maintainance will continue only as long as some customers will be willing to pay for it (current is 3.17.16 with 3.17.17 in development).

Version 3.18

This version is stable and maintained (current is 3.18.5 with 3.18.6 in development).

Version 3.19

This version is stable and maintained (current is 3.19.3 with 3.19.4 in development).

Version 3.20

This version is under development. It will try to reduce as much as possible the stock of patches in the state "reviewed", "awaiting review" and "in progress". If you have had something in the works that has not been accepted yet, please ready it for 3.20 and get it merged.

It should still include the work done for CWEP-002 (computed attributes and relations.

For details read list of tickets for CubicWeb 3.20.0.

Version 3.21

Removal of the dbapi, merging of Connection and ClientConnection, CWEP-003 (adding a FROM clause to RQL).

Version 4.0

When the work done for Pyramid will have been tested, it will become the default runner and a lot of things will be dropped: twisted, dead code, ui and core code that would be better cast into cubes, etc.

This version could happen early in 2015.

Cubes

New cubes and libraries

CWEPs

Here is the status of open CubicWeb Evolution Proposals:

CWEP-0002 full-featured implementation, to be merged in 3.20

CWEP-0003 patches sent to the review. . Champion will be adim.

Work in progress

PyConFR

Christophe will try to present at PyConFR the work he did on getting CubicWeb to work with Pyramid.

Pip-friendly source layout

Logilab and Christophe will try to make CubicWeb more pip/virtualenv-friendly. This may involve changing the source layout to include a sub-directory, but the impact on existing devs is expected to be too much and could be delayed to CubicWeb 4.0.

Pyramid

Christophe has made good progress on getting CubicWeb to work with Pyramid and he intends to put it into production real soon now. There is a Pyramid extension named pyramid_cubicweb and a CubicWeb cube named cubicweb-pyramid. Both work with CubicWeb 3.19. Christophe demonstrated using the debug toolbar, authenticating users with Authomatic and starting multiple workers with uWSGI.

Early adopters are now invited to jump in and help harden the code!

Agenda

Logilab's next roadmap meeting will be held at the beginning of november 2014 and Christophe and Dimitri were invited.

[logilab] Report from DebConf14

Publié le 2014-09-05 16:21:00

Last week I attended DebConf14 in Portland, Oregon. As usual the conference was a blur, with lots of talks, lots of new people, and lots of old friends. The organizers tried to do something different this year, with a longer conference (9 days instead of a week) and some dedicated hack time, instead of a pre-DebConf "DebCamp" week. That worked quite well for me, as it meant the schedule was not quite so full with talks, and even though I didn't really get any hacking done, it felt a bit more relaxed and allowed some more hallway track discussions.

http://www.logilab.org/file/264666/raw/Screenshot%20from%202014-09-05%2015%3A09%3A38.png

On the talks side, the keynotes from Zack and Biella provided some interesting thoughts. Some nice progress was made on making package builds reproducible.

I gave two talks: an introduction to salt (odp),

http://www.logilab.org/file/264663/raw/slide2.jpg

and a report on the Debian jessie release progress (pdf).

http://www.logilab.org/file/264665/raw/slide3.jpg

And as usual all talks were streamed live and recorded, and many are already available thanks to the awesome DebConf video team. Also for a change, and because I'm a sucker for punishment, I came back with more stuff to do.

[logilab] Logilab à EuroSciPy 2014

Publié le 2014-09-03 13:02:00
http://www.euroscipy.org/2014/site_media/static/symposion/img/logo.png

Logilab était présent à EuroSciPy2014 à Cambridge la semaine dernière, à la fois pour suivre les travaux de la communauté scientifique, et pour y présenter deux posters.

Performances

Il y a encore beaucoup été question de performances, au travers de tutoriels et de conférences de grande qualité :

  • une Keynote de Steven G. Johnson expliquant comment le langage Julia, de haut niveau et à typage dynamique parvient à atteindre des performances dignes du C et du Fortran dans le domaine numérique : le langage a été conçu pour être compilé efficacement avec un jit (just-in-time compiler) basé sur LLVM , en veillant à rendre possible l'inférence des types du maximum de variables intermédiaires et des retours des fonctions à partir des types d'entrée, connus au moment de leur exécution. L'interfaçage bidirectionnel avec le Python semble très simple et efficace à mettre en place.
  • un tutoriel de Ian Ozswald très bien construit, mettant bien en avant la démarche d'optimisation d'un code en démarrant par le profiling (cf. aussi notre article précédent sur le sujet). Les différentes solutions disponibles sont ensuite analysées, en montrant les avantages et inconvénients de chacune (Cython, Numba, Pythran, Pypy).
  • l'histoire du travail d'optimisation des forêts d'arbres décisionnels (random forests) dans scikit-learn, qui montre à quel point il est important de partir d'une base de code saine et aussi simple que possible avant de chercher à optimiser. Cet algorithme a été entièrement ré-écrit de façon itérative, conduisant au final à l'une des implémentations les plus rapides (sinon la plus rapide), tous langages confondus. Pour parvenir à ce résultat des formulations adroites de différentes parties de l'algorithme ont été utilisées puis optimisées (via Cython, une ré-organisation des données pour améliorer la contiguïté en mémoire et du multi-threading avec libération du GIL notamment).
  • la présentation de Firedrake, un framework de résolution d'équations différentielles par la méthode des éléments finis, qui utilise une partie de FEniCS (son API de description des équations et des éléments finis à utiliser) et la librairie PyOP2 pour assembler en parallèle les matrices et résoudre les systèmes d'équations sur GPU comme sur CPU.
  • la présentation par Jérôme Kieffer et Giannis Ashiotis de l'ESRF de l'optimisation de traitements d'images issues de caméras à rayons X haute résolution débitant 800Mo/s de données en utilisant Cython et du calcul sur GPU.

Autres sujets remarqués

D'autres sujets que je vous laisse découvrir plus en détails sur le site d'EuroSciPy2014 prouvent que la communauté européenne du Python scientifique est dynamique. Parmi eux :

  • un tutoriel très bien fait d'Olivier Grisel et Gaël Varoquaux sur l'analyse prédictive avec scikit-learn et Pandas.
  • une belle présentation de Gijs Molenaar qui a créé une belle application web pour présenter les données d'imagerie radioastronomiques issues du LOFAR.
  • enfin, Thomas Kluyver et Matthias Bussonnier nous ont notamment parlé du projet Jupyter qui permet d'utiliser le notebook IPython avec des noyaux non Python, dont Julia, R et Haskell.

Posters

Logilab a eu l'opportunité de prendre part au projet de recherche PAFI (Plateforme d'Aide à la Facture Instrumentale), en développant une application WEB innovante, basée sur CubicWeb, visant à la fois à faciliter le prototypage virtuel d'instruments (à vent pour le moment) et à permettre des échanges de données entre les acteurs de la recherche et les facteurs d'instrument, voire les musées qui possèdent des instruments anciens ou exceptionnels. La plateforme met ainsi en œuvre la Web Audio API et un modèle de collaboration élaboré.

L'autre poster présenté par Logilab concerne Simulagora, un service en ligne de simulation numérique collaborative, qui permet de lancer des calculs dans les nuages (donc sans investissement dans du matériel ou d'administration système), qui met l'accent sur la traçabilité et la reproductibilité des calculs, ainsi que sur le travail collaboratif (partage de logiciel, de données et d'études numériques complètes).

Un grand merci à l'équipe d'organisation de l'événement, qui a encore remporté un joli succès cette année.

[afpyro] AFPyro à Lyon - le 27 août 2014

Publié le 2014-08-27 00:00:00

Un Afpyro aura lieu le mercredi 27 août à partir de 19h au Tooley’s - 7 quai Fulchiron - Lyon 5éme (probablement sur la terrasse côté rue Monseigneur Lavarenne, si le temps le permet).

Aucune présentation n’est prévue, mais nous pourrons discuter autour des dernières actualités sur Python, et ceux qui sont allés à Europython pourrons en parler autour d’un verre.

Pour se rendre au Tooley’s :
  • en métro : arrêt Vieux Lyon
  • en vélo’v : stations Place Crépu, Saint Jean, Place Gourjus
  • en bus : bus 31 ou C20, arrêt Saint Georges

[Biologeek] Un web omni-présent

Publié le 2014-08-26 11:00:00

Intervention donnée lors des Rencontres de Lure, avec pour thème CHEMINS DE FAIRE, ACTIVER LA PAGE BLANCHE // Traverse. 1h et un public inconnu, bien éloigné de ma zone de confort…

J’ai emprunté plusieurs chemins de traverse au cours de ma vie. Le premier a été de passer de la biologie à l’informatique et plus particulièrement au web. Puis j’ai assez rapidement décidé de travailler à mon compte pour avoir plus de liberté. Je suis ensuite allé au Japon pendant un an pour explorer une nouvelle culture, d’autres modes de vie et de pensée. Et enfin j’ai co-créé une SCOP de retour en France il y a 2 ans. Chacune de ces expériences a été l’occasion de repartir d’une page blanche. Ou presque. De faire en sorte que mon passé et ma culture soient des acteurs de nouvelles interactions dans de nouveaux domaines.

En découvrant le web, j’ai exploré un monde de relations qui n’était finalement pas si éloigné de la biologie. En découvrant la vie de freelance, j’ai pris conscience des enjeux et des responsabilités qui incombent à un chef d’entreprise, chaque client devenant un petit patron. En découvrant le Japon, j’ai appris à apprécier les singularités de la culture française. En découvrant la collaboration, j’ai été confronté aux difficultés d’une approche démocratique.

Aujourd’hui, on expérimente avec scopyleft l’activation de la page blanche des autres pour arriver ensemble à produire le plus de valeur. On a essayé l’agilité avant de se rendre compte qu’il fallait travailler en amont même des projets en s’inspirant des méthodes du Lean Startup (et notamment du Lean Canvas). La vérification de la pertinence d’une idée peut être obtenue avant même de plonger dans la technique à travers des interviews ou des « produits embryons ».

Je me représente le web comme cet univers en expansion. On en définit mal les contours — on sait qu’il s’agit d’amas d’amas de galaxies — que l’on se représente plus ou moins sphérique. Parmi cette multitude d’étoiles, des planètes se sont formées et certaines se trouvent être à des conditions de pression et de température favorables à l’apparition de rencontres. J’ai l’impression d’être un astéroïde qui a atterri par hasard sur la planète des Rencontres de Lure. Afin que l’on partage un vocabulaire commun, j’ai posé 3 questions pour que l’on puisse échanger durant l’heure qui a suivi :

  • Quels sont ceux d’entre vous qui travaillent dans le web ?
  • Quels sont ceux parmi vous qui codent pour le web (html, css, js) ?
  • Quels sont ceux qui ont un compte Facebook ? Twitter ? Gmail ?

Un web

The problem with a centralized web is that the few points of control attract some unsavory characters. […] It’s not just possible, but fairly common for someone to visit a Google website from a Google device, using Google DNS servers and a Google browser on the way.

The Internet With A Human Face

On appelle souvent le web « la toile » ce qui lui donne une représentation concentrique avec l’araignée généralement au centre. C’est une assez mauvaise image du web originel, malheureusement cette métaphore tend à se rapprocher du web actuel. Nous sommes partis d’un web plus ou moins acentré pour arriver à un web qui ressemble à une télévision sur lequel on zappe entre 6 onglets (Google, Facebook, Twitter, Instagram, Wikipedia, Amazon). Cette position donne à ces monopoles une situation préoccupante à triple titre :

  • Ils peuvent fragmenter le web. Certains contenus, certaines données, ne deviennent accessibles qu’en faisant partie de la plateforme. En publiant sur ces sites, vous êtes acteurs de cette fragmentation sous couvert d’élitisme/snobisme.
  • Ils peuvent filtrer le web. Les algorithmes mis en place pour vous afficher les contenus de manière pertinente sont des œillères dangereuses. En ne consultant que ces sources d’information vous devenez prisonniers de bulles de complaisance bien lisses.
  • Ils peuvent monétiser le web. À partir de vos données, de vos relations, de vos interactions, de vos simples explorations. Votre profil prend de la valeur si vous êtes malade, si vous êtes dépensier, si vous tombez enceinte !

Les amas de galaxies dont je parlais en introduction s’agrègent et perdent de leur hétérogénéité. Comment évoluera un réseau en pair à pair avec de telles inégalités entre les pairs ?

On assiste également à une app-ification du web qui sous couvert de simplicité transforme vos interactions à travers le réseau en passant par des boîtes noires qui n’ont plus ni la simplicité des technologies web, ni la lisibilité de leur code.

La diversité sur le web se réduit à tel point qu’une page personnelle vous fait aujourd’hui passer pour un marginal. Voire un suspect ?

Omni

Le coût de la surveillance est beaucoup trop bas.

Lettre aux barbus, Laurent Chemla

On parle beaucoup d’Internet of Things, de Quantified Self ou d’OpenData avec l’idée derrière tout cela que beaucoup de données (Big Data — BINGO!) vont transiter entre nous, nos objets et notre environnement au sens large pour enrichir des hipsters de la silicon valley nous simplifier la vie.

Malheureusement ce dont on s’est aperçu avec Snowden et depuis, c’est que ces données servent surtout à nous tracer à grande échelle. Cette surveillance généralisée est préoccupante pour 3 raisons :

  • Perte de confiance dans le politique. C’était déjà pas la joie mais alors là c’est à vous faire douter de votre intérêt pour la citoyenneté. Les acteurs en puissance ont tout à gagner à ce qu’on les laisse s’amuser entre eux. Mais ce n’est plus de la démocratie…
  • Sentiment d’insécurité et lissage de l’opinion. Si chaque citoyen devient suspect, il faut se fondre dans la masse. Pour tromper les algorithmes, pour tromper les (futurs) drones, pour finir par se tromper soi-même. Et lorsqu’on s’est suffisamment conformé au moule on tape sur la minorité voisine pour évacuer son stress et se sentir vivant. Ou on retweete une cause vraiment juste… mais passagère aussi.
  • Renoncement à une vie privée numérique. Puisque plus rien ne marche, autant vivre avec et arrêter d’essayer de se battre contre des moulins. De toute façon ceux qui ont peur doivent bien avoir quelque chose à cacher ? Ou peut-être que l’on a envie d’un web intime, d’un web qui autorise les erreurs, d’un web qui dénonce les injustices ?

Devant cette surveillance généralisée, pour vivre heureux vivons submergés ?

Présent

Seven generation sustainability is an ecological concept that urges the current generation of humans to live sustainably and work for the benefit of the seventh generation into the future.

Great Law of the Iroquois

Internet n’oublie jamais. On a tous entendu cet adage qui est pourtant relativement faux. Des pages, des photos, des données disparaissent tous les jours. Lorsqu’un service ferme ce sont des milliers, voire des millions de comptes qui sont perdus. J’ai d’ailleurs appelé cela un datacide lorsque l’on assiste à un génocide de données. Cela peut avoir des effets bénéfiques et l’on pense bien évidemment au droit à l’oubli mais le problème est qu’Internet n’agit pas comme une souvenance — la façon dont on se souvient de ce que l’on a vécu — mais comme un journal de bord à moitié effacé. On ne choisit pas ce qui est conservé, on le subit.

Face à cette culpabilité numérique on en vient à une sorte d’exhibitionnisme numérique : plus je publie et moins les choses que je souhaite cacher seront visibles. On obtient des flux sans réflexion, sans espoir d’archivage, sans aucun contrôle. Le lâcher-prise sur ses interactions en ligne est symptomatique d’une inconscience généralisée de l’usage qui peut en être fait.

Ouf ! On a survécu à l’introduction un peu déprimante (j’ai réussi à plomber l’ambiance de typographes — huhu). Si l’on analyse chacun des points de ce web omni-présent, on constate qu’il y a principalement un problème de confort. Le web se fragmente car on ne prend pas la peine d’avoir son propre serveur, se surveille massivement car on est paresseux sur le chiffrement et disparait car l’on n’a pas envie de se soucier de ses traces numériques. Quelles pistes non techniques pour un web plus sain ?

Pistes

Militer

Le militantisme peut avoir un impact s’il est pratiqué à large échelle. La force du web est de pouvoir transmettre et propager des informations très rapidement. Il faut se servir de cet outil à bon escient !

Déconnecter

Je vais prendre mon exemple : je n’ai pas de compte Facebook, j’ai fait plusieurs diètes de tweets, je n’ai plus de smartphone. C’est certainement extrême mais je n’en suis pas mort numériquement pour autant. Je me porte même plutôt mieux depuis. S’interroger sur ses usages permet de prendre conscience de ce qui a vraiment de la valeur.

Innover localement

Je fonde beaucoup d’espoirs dans les initiatives locales. De nombreux projets sont en gestation et se développent autour de petites communautés de façon décentralisée. Une façon de s’adapter à la culture locale, de recréer une sorte d’intimité numérique.

Éduquer

Cette dynamique d’ouverture ne se fera pas sans éducation. Pas seulement auprès des enfants, on n’a malheureusement pas le luxe d’attendre que les nouvelles générations représentent la majorité. Il faudrait une éducation citoyenne de masse, 100 personnes aujourd’hui qui transmettront demain à 1000 autres ? ;-)

Se réapproprier

En utilisant des outils conviviaux tels que les défini Ivan Illich :

  • ne doit pas dégrader l’autonomie personnelle en se rendant indispensable
  • ne suscite ni esclave, ni maître
  • élargit le rayon d’action personnel

Il est temps de se réapproprier ses savoirs pour être à même de réacquérir son autonomie et en offrir à d’autres.

La concentration de galaxies est à l’origine d’une augmentation de la température qui se termine généralement en trous noirs. Quels autres leviers avons-nous pour éviter que le web ne soit aspiré par ces trous noirs ? J’ai démarré le discussion avec cette citation :

Il faut choisir, se reposer ou être libre.

Thucydide, ~2400 av. Facebook

Discussion

Questions techniques

Beaucoup de discussions sur la faisabilité technique d’une telle surveillance. Si l’on fait un premier point sur l’affaire Snowden, le constat est on ne peut plus limpide. C’est même pire après tout ce qui a été découvert depuis…

Questions sur la peur

On m’a demandé de quoi est-ce que j’avais peur, ressortant le fameux Nothing to hide, nothing to fear. Je n’ai pas peur, je m’interroge sur un constat et sur ma participation indirecte à la situation actuelle en étant acteur de ce système. J’explore des solutions et je vais en chercher dans des lieux comme les rencontres de Lure pour y retrouver une certaine naïveté technique et une expérience vieille de quelques millénaires.

Solutions techniques

Il m’a quand même été demandé de donner quelques solutions techniques. Voici des propositions :

Ces 4 points sont très basiques, vous pouvez ensuite vous pencher sur des solutions comme les réseaux privés virtuels (VPN) ou Tor pour aller plus loin.

Le web est une invention précieuse, préservons son graphe : ses liens et ses données.

[AFPy-Nantes] 40 pythons, 1 conférence et des trolls

Publié le 2014-08-25 22:00:00

Nous étions nombreux mardi dernier aux conférences. À la louche, une quarantaine. Un groupe assez hétérogène composé de curieux comme d'experts.

Deux sujets ont donc été abordés, merci à Florent et Alex pour leur préparation :).

Ci-dessous, le compte-rendu de près de 2h de conférence :).

Django, framework web

Intervenant : Florent

Les slides de la présentation sont disponibles ici : Introduction à Django

chapter Part I: Django Django

Présentation

Django est donc un framework pour le web développé dans l'optique d'être rapide à configurer et déployer. Ainsi, il présente un haut niveau d'abstraction. Étant un projet open-source, il est assez facile de l'étendre.

La dernière release est 1.6 et celle à venir, 1.7, devrait présenter des mises à jour de fond, tel un système de migration intégré : django-migrations.

Le projet est développé selon les philosophies KISS (Keep It Shot & Simple) et DRY (Don't Repeat Yourself). Si le premier objectif est bien rempli, il semble que le second soit sujet à débat. On notera différents avantages à django, notamment son installation très facile ainsi que son excellente documentation. Il dispose également d'une communauté très active.

Sous le capot ?

Concernant les aspects techniques, l'environnement classique est une version 1.6 du framework sous python 2.7. Django est compatible python 3 mais ce n'est pas le cas de tous les modules qui peuvent s'y ajouter. Pour la partie serveur, il semble qu'il s'intègre correctement derrière tout et n'importe quoi (apache, nginx,...). Du côté base de données (BDD), django fonctionne essentiellement avec SQL (MySQL, PostgreSQL, SQLite). Il est possible de l'interfacer avec des bases NoSQL, mais il faut garder en tête que tout le framework est pensé pour intéragir avec des bases de données relationnelles.

Pour ce qui est de la création de site, Django repose sur un modèle type MVC (modèle-vue-contrôleur) qui sera appelé MTV (modèle-template-vue). Les modèles, qui décrivent les objets stockés en base, sont écrits en Python. Cela rend la configuration intuitive. Il est à noter que le moteur de template, semblable à Jinja en terme de syntaxe, est réputé comme étant lourd et lent.

En pratique...

Après toute cette théorie, démonstration rapide avec la mise en place d'un site pour recenser les coins à champignons. C'est l'occasion d'observer la rapidité avec laquelle il est possible de déployer un nouveau site (environ 4 commandes ^^). Cerise sur le gâteau, Django génère automatiquement une interface d'administration contenant formulaire et tout ce qu'il faut pour gérer le contenu de la BDD (opérations CRUD). L'administration d'un projet se fait essentiellement via le script manage.py.

Django sépare les modules métiers sous forme d'applications. Chacune contenant un fichier models.py, views.py, admin.py et tests.py (pour vous encourager à créer des tests unitaires). Les modèles se déclarent sous forme de classes Python dont les champs sont des colonnes en base. Il est possible d'étendre facilement les types de champs pour créer des types spécifiques, autre que ceux de SQL.

Concernant la définition des routes, comme souvent, elle se fait via l'utilisation de schémas et d'expressions régulières. Ici, on découvre avec plaisir que Django repère automatiquement lorsqu'un fichier est modifié et redéploie.

Aller plus loin

Les bases de Django en poche, on évoque rapidement les fonctionnalités avancées. Notamment de l'héritage sur les modèles, à la fois puissant mais rapidement complexe. Des mécanismes similaires existent sur les vues et les templates.

Django présente aussi des fonctionnalités d'internationnalisation, tant pour les URL que pour le contenu.

Pour la gestion des login, la notion de groupes, d'utilisateur et de droits est pré-intégrée et est aisément personnalisable.

Il est ressorti des questions que Django possède un système de rétro-spécification, capable de définir les fichiers modèles nécessaires décrivant une BDD pré-existante, très utile quand combiné avec des modules de migration, type south (c.f. ci-après).

Les modules

Que serait un framework (open-source) sans ses plugins & modules ? La communauté étant active, il existe de nombreux modules très utiles, il ressort de la conférence :

  1. South. Un outil pour effectuer des migrations de base de données. Un exemple de cas d'utilisation : l'intervenant devait migrer une vieille application vers Django. Parmi les problèmes, il faisait face à la structure SQL de très mauvaise qualité (du genre clé étrangère non unique...). A l'aide de l'outils de rétro-spécification de Django, il a été capable de récupérer les définitions des modèles et de corriger la BDD grâce à South. Hallelujah ! Comme mentionné plus haut, la version 1.7 de Django intègre un tel module (essentiellement basé sur South). Cela peut également être très utile pour manipuler différentes bases sur différents serveurs (dev, prod, pre-prod,...).
  2. django-extensions: utilitaire pour manage.py ajoutant des commandes pour faciliter l'administration.
  3. django-debug-toolbar: outil pour faire du profiling dans le navigateur.
  4. factory-boy: création de grappes de données pour le test (Déclaration de factory). Par rapport à l'utilisation de fixtures, il permet un maintien plus facile des données de test. De plus, la gestion des clés étrangères est très pratique.
  5. Un module shop très différent de prestashop. Beaucoup plus modulaire que ce dernier (donc pas solution out of the box).

Conclusion & commentaires

Ce petit tour d'horizon nous aura permis de constater l'extrême rapidité de développement qu'offre Django. Énorme avantage également, sa large bibliothèque de modules.

Concernant la question du choix du framework web, il existe des alternatives à Django. Pour choisir ce dernier, c'est l'usage final qui est déterminant. Bien que Django soit rapide et efficace, il est en revanche très monolythique. Si vous comptez utiliser un autre ORM par exemple, un framework plus modulaire serait Pyramid. Enfin, il existe des framework très léger comme Flask.

L'inévitable comparaison avec d'autres langages tels que PHP était plutôt sans appel (l'occasion pour certains templiers/trolls de partir en croisade contre Symfony :)). PHP est jugé (très) lourd et peu efficace. Il y avait d'ailleurs parmi nous 3 personnes qui souhaitaient quitter l'univers PHP au profit de Python.

Finalement, Django présente quelques points noirs, tels que la personnalisation de l'interface d'administration ou bien la gestion de pages multi-formulaires. Si ces dernières se complexifient, leur maintien devient vite très difficile.

Quelques liens pour se documenter :

Questions

Les questions ont fait ressortir les points suivant.

Il est aisé de définir plusieurs environnements (prod, pre-prod, dev) via les fichiers de configuration. Le script settings.py (configuration générale) se charge ensuite de sélectionner la configuration appropriée en fonction de l'environnement.

Pour les tests unitaires, les capacités de test de Python sont très utiles. Ainsi que le module LiveServerTestCase pour tester les requêtes réellement à travers de réelles requêtes HTTP.

Il est possible d'utiliser Django sans installer un SGBD relationnel sur son poste, grâce à SQLite. L'utilisation du framework sans base de donnée du tout se limitera à l'utilisation du routage d'URL, des vues et des templates. Dans un tel cas d'utilisation, un coup d'oeil à un framework plus léger comme Flask (c.f. plus haut) est conseillé.

Python, les bonnes pratiques.

Intervenant : Alex

Les slides de la présentation sont disponibles ici : Écrire du code vraiment pythonique

Vous voulez coder en Python ? D'accord, mais pas n'importe comment ! Les bonnes pratiques facilitent la relecture du code et le maintien que cela soit par un tier ou par son auteur lui-même. Il ne faut pas oublier qu'on laisse parfois nos projets personnels un peu en suspend, et lorsqu'on les reprend, on est alors un étranger dans sa propre maison. Au cas où, mieux vaut baliser le terrain ;).

Notre intervenant commence par quelques généralités sur Python, sa syntaxe et sa philosophie. "Python essaie d'être élégant", voilà une des premières choses qu'on entend. Par rapport à d'autres langages (e.g. Ruby) qui recherchent en plus la pureté. Pour le développeur Python, la pureté n'est pas une fin en soi. c.f. The Zen of Python que je cite " Special cases aren't special enough to break the rules. Although practicality beats purity". En bref, un mot très important : pragramatisme (practicality).

Coder proprement, ça ne s'invente pas, encore moins quand on débute et les gens qui travaillent avec Python y réfléchissent. Du coup il existe un guide de références définissant les bonnes pratiques, on l'appelle le PEP8. Derrière ce terme à l'apparence obscure de PEP (Python Enhancement Proposals) se cache tout simplement des propositions d'amélioration du langage, qu'elles soient techniques ou formelles.

Pour ce qui est de la mise en pratique du PEP8, je me permets de vous renvoyer aux slides de la présentation qui seront plus clairs et exhaustifs. Cependant, durant la présentation, quelques points sont ressortis plus que d'autres. Je continue donc avec une liste non exhaustive...

D'abord, il existe des outils pour suivre les lignes directrices (guide lines) comme flake8 qui vérifie le respect du PEP8 (il en existe d'autres !). Mais plus simple encore, l'easter egg (introduit par le PEP20) du import this qui affiche le Zen of Python.

Concernant les entrées d'un programme, une bonne habitude est de traiter les données en deux fois :
  1. Normaliser l'entrée
  2. Traiter la donnée normalisée

Cela permet de simplifier le code, notamment celui du traitement qui est du coup toujours le même. Donc, évitez d'avoir à gérer trop de cas d'erreurs (excpetions) dans le code de traitement. On notera ici la phrase célèbre de Jon Postel : "Be liberal in what you accept, and conservative in what you send". Qu'on pourrait traduire par : soyer souple pour vos entrées, intransigent pour vos sorties.

On a aussi parlé des tuples, structure de données constantes (immutable) très pratique pour passer de la donnée à une fonction. Attention cependant à ne pas en abuser. Si de nombreux traitements sont inhérents à vos tuples, vous avez peut-être besoin d'un objet (classe) pour mieux gérer tout ça (e.g. points en mathématique...). Pour un type point en Mathématiques, peut-être qu'une classe est plus adaptée. VOus pourrez alors profiter de la surcharge d'opérateur pour implémenter les opérations spécifiques.

A plusieurs reprises nous avons mentionné les dictionnaires, c'est un synonyme de tableau associatif, i.e. un ensemble clé-valeur.

Autre point fort, les ContextManager, ces objets qu'on utilise grâce au mots clés with-as. Ils sont une fonctionnalité très importante du langage qui permet de bien maîtriser la portée des variables. Par exemple pour l'ouverture et la fermeture d'un fichier, ou encore pour la création et l'excécution d'une requête dans Django :).

A propos des lambda functions, ces petits bouts de code très courts qui n'acceptent qu'une expression pour seule opération, rappel qui a son importance : pas de unpacking de tuple dans les paramètres (c.f. slydes et tuples pour la notion de unpacking).

Le mot de la fin

Les slides des deux présentations sont disponibles ici:

On a vu et appris plein de choses, c'était super ! A la prochaine fois, et d'ici là, codez bien !

[logilab] Logilab at Debconf 2014 - Debian annual conference

Publié le 2014-08-21 19:07:00

Logilab is proud to contribute to the annual debian conference which will take place in Portland (USA) from the 23rd to the 31st of august.

Julien Cristau (debian page) will be giving two talks at the conference :

http://www.logilab.org/file/263602/raw/debconf2014.png

Logilab is also contributing to the conference as a sponsor for the event.

Here is what we previously blogged about salt and the previous debconf . Stay tuned for a blog post about what we saw and heard at the conference.

https://www.debian.org/logos/openlogo-100.png

[tarek] ToxMail Experiment Cont'd

Publié le 2014-08-03 19:33:00

I started the other day experimenting with Tox to build a secure e-mailing system. You can read my last post here.

To summarize what Toxmail does:

  • connects to the Tox network
  • runs a local SMTP and a local POP3 servers
  • converts any e-mail sent to the local SMTP into a Tox message

The prototype is looking pretty good now with a web dashboard that lists all your contacts, uses DNS lookups to find users Tox Ids, and has a experimental relay feature I am making progress on.

See https://github.com/tarekziade/toxmail

DNS Lookups

As described here, Tox proposes a protocol where you can query a DNS server to find out the Tox ID of a user as long they have registered themselves to that server.

There are two Tox DNS servers I know about: http://toxme.se and http://utox.org

If you register a nickname on one of those servers, they will add a TXT record in their DNS database. For example, I have registered tarek at toxme.se and people can get my Tox Id querying this DNS:

$ nslookup -q=txt tarek._tox.toxme.se.
Server:     212.27.40.241
Address:    212.27.40.241#53

Non-authoritative answer:
tarek._tox.toxme.se text = "v=tox1\;id=545325E0B0B85B29C26BF0B6448CE12DFE0CD8D432D48D20362878C63BA4A734018C37107090\;sign=u+u+sQ516e9VKJRMiubQiRrWiVN0Nt98dSbUtsHBEwYiaQHk2T8zAq4hGprMl9lc89VXRnI+AukoqpC7vJoHDXRhcmVrVFMl4LC4WynCa/C2RIzhLf4M2NQy1I0gNih4xjukpzRwkA=="

Like other Tox clients, the Toxmail server uses this feature to convert on the fly a recipient e-mail into a corresponding Tox ID. So if I write an e-mail to tarek@toxme.se, Toxmail knows where to send the message.

That breaks anonymity of course, if the Tox Ids are published on a public server, but that's another issue.

Offline mode

The biggest issue of the Toxmail project is the requirement of having both ends connected to the network when a mail is sent.

I have added a retry loop when the recipient is offline, but the mail will eventually make it only when the two sides are connected at the same time.

This is a bit of a problem when you are building an asynchronous messaging system. We started to discuss some possible solutions on the tracker and the idea came up to have a Supernode that would relay e-mails to a recipient when its back online.

In order to do it securely, the mail is encrypted using the Tox public/private keys so the supernode don't get the message in clear text. It uses the same crypto_box APIs than Tox itself, and that was really easy to add thanks to the nice PyNaCL binding, see https://github.com/tarekziade/toxmail/blob/master/toxmail/crypto.py

However, using supernodes is adding centralization to the whole system, and that's less appealing than a full decentralized system.

Another option is to use all your contacts as relays. A e-mail propagated to all your contacts has probably good chances to eventually make it to its destination.

Based on this, I have added a relay feature in Toxmail that will send around the mail and ask people to relay it.

This adds another issue though: for two nodes to exchange data, they have to be friends on Tox. So if you ask Bob to relay a message to Sarah, Bob needs to be friend with Sarah. And maybe Bob does not want you to know that he's friend with Sarah.

Ideally everyone should be able to relay e-mails anonymously - like other existing systems where data is just stored around for the recipient to come pick it.

I am not sure yet how to solve this issue, and maybe Tox is not suited to my e-mail use case.

Maybe I am just trying to reinvent BitMessage. Still digging :)

[Biologeek] Héritage et immobilier

Publié le 2014-08-01 11:00:00

— Tu n’en as pas marre de payer un loyer ?
— Non, tirade sur la propriété, fléau de cette société.
— Mais pour ton fils ?!!!

La discussion revient souvent donc pour clarifier :

  • Faire un achat immobilier consiste à s’endetter et donc à se condamner à assurer un revenu sur x années. Cela réduit considérablement les options possibles pour passer plus de temps avec mon fils. Le loyer est le prix de cette flexibilité.
  • Acquérir une maison c’est s’immobiliser et donc renoncer à une vie nomade permettant de rencontrer d’autres cultures. Je ne souhaite pas que du matériel vienne entraver une soif de découverte et d’expériences. Le loyer est le prix de cette liberté.
  • Léguer c’est déchirer une famille, je n’ai pas vu un seul héritage dans mon entourage qui se soit déroulé sans accrocs. Je ne pense pas que le gain soit à la hauteur de l’enjeu. Vraiment. Le loyer est le prix de cette intégrité.

J’espère que mon fils aura hérité de bien d’autres choses pour être autonome, bienveillant et heureux dans la vie. La richesse que je lui propose d’accumuler n’est pas matérielle, elle ne se mesure pas en m², elle n’est pas spéculative non plus. La chose la plus importante dont il a besoin c’est de l’attention et du temps de tendresse disponible.

Pas un tas de cailloux.

[AFPy-Nantes] Fin des vacances, Nantes se replonge dans Python :)

Publié le 2014-07-31 22:00:00

Tout le monde est bien reposé, il est de temps de se replonger dans le bain. Rien de tel qu'un meetup de rentrée !

Deux sujets de présentations vous seront proposés:

  • « Introduction à Django, le framework de développement web pour les perfectionnistes sous pression. »
  • « Écrire du code python selon les règles de l’art. »

La suite du meetup et de la soirée nous laissera le temps de discuter librement et d'aller boire un verre pour profiter de cette fin de période estivale.

Que vous soyez experts Python, débutants ou simplement curieux de découvrir ce langage, nous serons heureux de vous compter parmis nous !

L'évènement est publié sur le site de la Cantine: Meetup Python #4.

À bientôt, et en attendant ... respectez la PEP8 :)

[Biologeek] Jeune photographe

Publié le 2014-07-31 11:00:00

Accepter les photographies que nous avons faites comme elles sont devient alors un acte d’accompagnement du mouvement permanent du monde. On ne fait pas toujours des photographies comme on embaume des cadavres. On en fait aussi parfois comme on cueille des fleurs, en sachant nos sensations périssables, pour le plaisir d’accompagner leur évanouissement fugitif ou de rendre hommage à la beauté du monde. Et on en fait parfois comme on planterait des graines, en attente de la floraison à venir.

En attente d’une floraison à venir, Serge Tisseron

Jeune photographe, tu vas te réfugier dans la technique. Les focales et les boîtiers n’auront plus de secret pour toi. Tu manieras l’exposition, la composition, le bokeh et le flou cinétique comme un pro. Tu feras de belles photos. La technique est rassurante et rationnelle, elle fait partie du domaine du connu en se rapprochant de ce qui est enseigné à l’école. Malheureusement, la technique est aux antipodes des émotions. La maîtrise d’un outil peut réduire son expression artistique et sa créativité.

Jeune photographe, tu vas chercher des mentors. Les écouter, les aduler, les copier, parfois même les rencontrer. Examiner leur travail, méticuleusement, tirage après tirage pour comprendre la chaîne photographique. Leur expérience va te permettre de progresser rapidement, de connaître des astuces stylistiques et d’identifier les scènes qui ont du potentiel. Tu feras des photos artistiques. Malheureusement, ces sources d’inspiration étoufferont ton propre style. La photographie est avant tout l’expression de son soi profond et personnel.

Jeune photographe, tu vas être attiré par l’exotisme. Nu, N&B, contrées lointaines, macro, animalier, les catégories ne manquent pas pour se distinguer et sortir de la monotonie. Qu’il est reposant d’explorer en continu sans prendre le temps de s’ennuyer sur un domaine. Tu vas faire des photos attrayantes. Malheureusement, c’est dans cet ordinaire que résident les pépites artistiques. L’intimité photographique comme un partage de ces instants de vie.

Jeune photographe, surprends-toi !

Billet auto-critique suite à une twiscussion avec Éric, Karl et Emmanuel.

[AFPy-Nantes] Barcamp estival du 29 juillet 2014

Publié le 2014-07-30 22:00:00

Notre premier barcamp, animé par Georges nous a permis d'aborder différents sujets en groupes de 3 à 5 personnes pendant 45 minutes environ.

Les comptes-rendus sont ci-dessous, rendez-vous à la prochaine rencontre !

barcamp estival du 29 juillet 2014

Outils Python pour les adminsys/devops

Participants : Florent, Antoine et Pablo

Rapporteur : Pablo

L'idée était de discuter des outils Python disponibles pour les adminsys.

Les point abordés étaient :

  • Les outils pour disponibles pour le déploiement/provisioning, comme Fabric http://www.fabfile.org/, Ansible http://www.ansible.com/home ou Saltstack http://www.saltstack.com/
  • Les nouvelles façons de travailler entre développeurs et administrateurs systèmes, Antoine nous a raconté son expérience avec Fabric et Puppet (Ruby) chez Wikipedia, nous avons évoqué la problématique du stockage/versioning de donnés sensibles et partagées dans une même équipe
  • Les outils de monitoring comme Graphite http://graphite.wikidot.com/ et ElasticSearch/Logstash/Kibana (Java) pour les métriques des apps/activités
  • L'utilisation de Sentry https://getsentry.com/ pour le tracking des erreurs/exception dans une application Python

Pour résumer, la discussion a été ouverte et variée. De plus, c'était la première fois que nous nous rencontrions et les échanges ont permis de mieux connaître l'intérêt et l'expérience de chacun sur le sujet, le tout dans une très bonne ambiance.

Django

Participants : Mathieu F., ?, ?, ?

Rapporteur : Mathieu F.

Nous avons évoqué les serveurs web et leurs modes "FastCGI" et WSGI".

FastCGI :

WSGI :

Nous avons ensuite rapidement parlé de Gunicorn (http://gunicorn.org/), un serveur web conçu pour Python et WSGI.

Puis Django :

  • framework de développement web
  • permet d'architecturer le code selon le modèle MVC
  • permet de définir une liste d'URL (exemple pour "www.monsite.fr" : /login, /blog, /admin, /voirArticle et d'associer une action / un script à chacune (ce que Symfony appelle des routes, dans le monde PHP ;-)
  • fournit une commande shell "manage.py" permet des actions de debug, initialisation, lancement du serveur web en local, etc
  • Django permet de créer un back office très light (CRUD) de manière presque automatique

Les "virtualenv" :

  • permettent de faire cohabiter des logiciels écrits en Python ayant des prérequis différents. Par exemple : le logiciel "Toto" requiert la lib "libA" en version 12, alors que le logiciel "Truc" requiert la lib "libA" en version 10
  • sont utiles (indispensables !) à la fois en environnement de dév et en prod
  • voir commandes "virtualenv", "virtualenvwrapper" et "venv"

Déploiement d'applis Django :

Hébergement :

Python 2.7 ou Python 3.x ? (troll inside ;-)
==> A ce jour, la seule raison de commencer un développement en 2.7 plutôt qu'en 3.x serait d'avoir un besoin impératif d'une lib non dispo en Python 3 (et dont le portage n'est pas envisagé). De très nombreuses libs ont été mises à jour, donc ce cas de figure devrait se raréfier.

Depuis la version 1.6, Django (https://www.djangoproject.com/) supporte Python 3.

Pour terminer, un petit lien vers un blog TRES intéressant sur Python (mais pas que ;-) :

Bonnes pratiques et outils python

Participants : Reine, Nicolas, Yoann

Rapporteur : Yoann

Tout d'abord, nous avons discuté de maisons d'édition chez qui paraissent des livres intéressants pour de la doc ou de l'outillage (Python/Linux mais pas que) : Packt, O'Reilly, Apress, No starch press. Nous avons aussi parlé de sites plus orientés Linux : TLLTS (The Linux Link Tech Show:podcasts sur youtube), Linux Luddites, distrowatch.

Ensuite, nous avons abordé la démarche générale à suivre dans les projets pour en venir plus particulièrement à l'outillage : en fonction des besoins du projet on choisit les technologies, puis vient le choix des outils. Avec Python, la référence permet généralement comprendre rapidement comment utiliser les librairies.

Enfin, nous avons parlé des virtualenv qui permettent d'avoir plusieurs environnements bien séparés sur une machine physique (et donc de disposer de différentes versions des librairies, voire de Python) ainsi que les importer/exporter grâce à pip, par l'intermédiaire d'un fichier listant les dépendances du projet.

Regards croisés sur des projets python

Participants : Jean D., Georges G., Jean-Baptiste, ?

Rapporteur : Jean D.

Python est recherché pour simplifier et debugger des développements existants. D'un accès facile sur le Web, il est également rapide d'apprentissage. Il permet de réduire la taille d'un développement classique. L'ordre de grandeur de cette réduction peut-être de 75 % du temps. Ceci grâce à 2 atouts principaux : son "moteur" performant ses nombreuses fonctionnalités.

[AFPy-Nantes] Rencontre et key signing party 24 mai 2014

Publié le 2014-07-30 22:00:00

Après le meetup-pilote qui nous a permis de découvrir GrapheekDB, cette rencontre avait pour principal objectif de faire connaissance et préparer les prochains évènements.

Il en est sortie l'idée d'organiser un meetup par mois en alternant conférences et barcamps.

Quelques sujets potentiels de présentations ont déjà émergés :

  • Initiation à Python ou comment écrire du code pythonesque pour ceux qui viennent d'autres langages
  • Retour d'expérience sur migration vers Python3
  • Python legacy avec Zope, Grok, etc.
  • Demo d'IPython Notebook avec un peu de dataviz
  • Programmation un Raspberry PI avec Python
  • Présentation/Introduction à Django
  • Retour d'expérience sur apps Django et bibliothèques sympas
  • Sites et blogs statiques avec Pelican
  • Générateurs et co-routines

La key signing party organisée par Pablo a permis d'animer la suite du meetup, en attendant la bière !

rencontre et key signing party

À bientôt, et en attendant ... respectez la PEP8 :)

[AFPy-Nantes] Retour sur le meetup du 09 avril 2014

Publié le 2014-07-29 22:00:00

Lors de ce premier meetup Python, où plus d'une vingtaine de personnes étaient présentes, Raphaël Braud nous a présenté GrapheekDB, une base de données de graphe libre !

Ce premier rendez-vous était surtout l'occasion de nous rencontrer et de discuter de l'organisation de nos prochaines rassemblements.

À bientôt, et en attendant ... respectez la PEP8 :)

[logilab] Pylint 1.3 / Astroid 1.2 released

Publié le 2014-07-28 15:21:00

The EP14 Pylint sprint team (more on this here and there) is proud to announce they just released Pylint 1.3 together with its companion Astroid 1.2. As usual, this includes several new features as well and bug fixes. You'll find below some structured list of the changes.

Packages are uploaded to pypi, debian/ubuntu packages should be soon provided by Logilab, until they get into the standard packaging system of your favorite distribution.

Please notice Pylint 1.3 will be the last release branch support python 2.5 and 2.6. Starting from 1.4, we will only support python greater or equal to 2.7. This will be the occasion to do some great cleanup in the code base. Notice this is only about the Pylint's runtime, you should still be able to run Pylint on your Python 2.5 code, through using Python 2.7 at least.

New checks

  • Add multiple checks for PEP 3101 advanced string formatting: 'bad-format-string', 'missing-format-argument-key', 'unused-format-string-argument', 'format-combined-specification', 'missing-format-attribute' and 'invalid-format-index'
  • New 'invalid-slice-index' and 'invalid-sequence-index' for invalid sequence and slice indices
  • New 'assigning-non-slot' warning, which detects assignments to attributes not defined in slots

Improved checkers

  • Fixed 'fixme' false positive (#149)
  • Fixed 'unbalanced-iterable-unpacking' false positive when encountering starred nodes (#273)
  • Fixed 'bad-format-character' false positive when encountering the 'a' format on Python 3
  • Fixed 'unused-variable' false positive when the variable is assigned through an import (#196)
  • Fixed 'unused-variable' false positive when assigning to a nonlocal (#275)
  • Fixed 'pointless-string-statement' false positive for attribute docstrings (#193)
  • Emit 'undefined-variable' when using the Python 3 metaclass= argument. Also fix 'unused-import' false for that construction (#143)
  • Emit 'broad-except' and 'bare-except' even if the number of except handlers is different than 1. Fixes issue (#113)
  • Emit 'attribute-defined-outside-init' for all statements in the same module as the offended class, not just for the last assignment (#262, as well as a long standing output mangling problem in some edge cases)
  • Emit 'not-callable' when calling properties (#268)
  • Don't let ImportError propagate from the imports checker, leading to crash in some namespace package related cases (#203)
  • Don't emit 'no-name-in-module' for ignored modules (#223)
  • Don't emit 'unnecessary-lambda' if the body of the lambda call contains call chaining (#243)
  • Definition order is considered for classes, function arguments and annotations (#257)
  • Only emit 'attribute-defined-outside-init' for definition within the same module as the offended class, avoiding to mangle the output in some cases
  • Don't emit 'hidden-method' message when the attribute has been monkey-patched, you're on your own when you do that.

Others changes

  • Checkers are now properly ordered to respect priority(#229)
  • Use the proper mode for pickle when opening and writing the stats file (#148)

Astroid changes

  • Function nodes can detect decorator call chain and see if they are decorated with builtin descriptors (classmethod and staticmethod).
  • infer_call_result called on a subtype of the builtin type will now return a new Class rather than an Instance.
  • Class.metaclass() now handles module-level __metaclass__ declaration on python 2, and no longer looks at the __metaclass__ class attribute on python 3.
  • Add slots method to Class nodes, for retrieving the list of valid slots it defines.
  • Expose function annotation to astroid: Arguments node exposes 'varargannotation', 'kwargannotation' and 'annotations' attributes, while Function node has the 'returns' attribute.
  • Backported most of the logilab.common.modutils module there, as most things there are for pylint/astroid only and we want to be able to fix them without requiring a new logilab.common release
  • Fix names grabed using wildcard import in "absolute import mode" (i.e. with absolute_import activated from the __future__ or with python 3) (pylint issue #58)
  • Add support in brain for understanding enum classes.

[logilab] EP14 Pylint sprint Day 2 and 3 reports

Publié le 2014-07-28 15:21:00
https://ep2014.europython.eu/static_media/assets/images/logo.png

Here are the list of things we managed to achieve during those last two days at EuroPython.

After several attempts, Michal managed to have pylint running analysis on several files in parallel. This is still in a pull request (https://bitbucket.org/logilab/pylint/pull-request/82/added-support-for-checking-files-in) because of some limitations, so we decided it won't be part of the 1.3 release.

Claudiu killed maybe 10 bugs or so and did some heavy issues cleanup in the trackers. He also demonstrated some experimental support of python 3 style annotation to drive a better inference. Pretty exciting! Torsten also killed several bugs, restored python 2.5 compat (though that will need a logilab-common release as well), introduced a new functional test framework that will replace the old one once all the existing tests will be backported. On wednesday, he did show us a near future feature they already have at Google: some kind of confidence level associated to messages so that you can filter out based on that. Sylvain fixed a couple of bugs (including https://bitbucket.org/logilab/pylint/issue/58/ which was annoying all the numpy community), started some refactoring of the PyLinter class so it does a little bit fewer things (still way too many though) and attempted to improve the pylint note on both pylint and astroid, which went down recently "thanks" to the new checks like 'bad-continuation'.

Also, we merged the pylint-brain project into astroid to simplify things, so you should now submit your brain plugins directly to the astroid project. Hopefuly you'll be redirected there on attempt to use the old (removed) pylint-brain project on bitbucket.

And, the good news is that now both Torsten and Claudiu have new powers: they should be able to do some releases of pylint and astroid. To celebrate that and the end of the sprint, we published Pylint 1.3 together with Astroid 1.2. More on this here.

[tarek] ToxMail experiment

Publié le 2014-07-26 11:22:00

I am still looking for a good e-mail replacement that is more respectful of my privacy.

This will never happen with the existing e-mail system due to the way it works: when you send an e-mail to someone, even if you encrypt the body of your e-mail, the metadata will transit from server to server in clear, and the final destination will store it.

Every PGP UX I have tried is terrible anyways. It's just too painful to get things right for someone that has no knowledge (and no desire to have some) of how things work.

What I aiming for now is a separate system to send and receive mails with my close friends and my family. Something that my mother can use like regular e-mails, without any extra work.

I guess some kind of "Darknet for E-mails" where they are no intermediate servers between my mailbox and my mom's mailbox, and no way for a eavesdropper to get the content.

Ideally:

  • end-to-end encryption
  • direct network link between my mom's mail server and me
  • based on existing protocols (SMTP/IMAP/POP3) so my mom can use Thunderbird or I can set her up a Zimbra server.

Project Tox

The Tox Project is a project that aims to replace Skype with a more secured instant messaging system. You can send text, voice and even video messages to your friends.

It's based on NaCL for the crypto bits and in particular the crypto_box API which provides high-level functions to generate public/private key pairs and encrypt/decrypt messages with it.

The other main feature of Tox is its Distributed Hash Table that contains the list of nodes that are connected to the network with their Tox Id.

When you run a Tox-based application, you become part of the Tox network by registering to a few known public nodes.

To send a message to someone, you have to know their Tox Id and send a crypted message using the crypto_box api and the keypair magic.

Tox was created as an instant messaging system, so it has features to add/remove/invite friends, create groups etc. but its core capability is to let you reach out another node given its id, and communicate with it. And that can be any kind of communication.

So e-mails could transit through Tox nodes.

Toxmail experiment

Toxmail is my little experiment to build a secure e-mail system on the top of Tox.

It's a daemon that registers to the Tox network and runs an SMTP service that converts outgoing e-mails to text messages that are sent through Tox. It also converts incoming text messages back into e-mails and stores them in a local Maildir.

Toxmail also runs a simple POP3 server, so it's actually a full stack that can be used through an e-mail client like Thunderbird.

You can just create a new account in Thunderbird, point it to the Toxmail SMPT and POP3 local services, and use it like another e-mail account.

When you want to send someone an e-mail, you have to know their Tox Id, and use TOXID@tox as the recipient.

For example:

7F9C31FE850E97CEFD4C4591DF93FC757C7C12549DDD55F8EEAECC34FE76C029@tox

When the SMTP daemon sees this, it tries to send the e-mail to that Tox-ID. What I am planning to do is to have an automatic conversion of regular e-mails using a lookup table the user can maintain. A list of contacts where you provide for each entry an e-mail and a tox id.

End-to-end encryption, no intermediates between the user and the recipient. Ya!

Caveats & Limitations

For ToxMail to work, it needs to be registered to the Tox network all the time.

This limitation can be partially solved by adding in the SMTP daemon a retry feature: if the recipient's node is offline, the mail is stored and it tries to send it later.

But for the e-mail to go through, the two nodes have to be online at the same time at some point.

Maybe a good way to solve this would be to have Toxmail run into a Raspberry-PI plugged into the home internet box. That'd make sense actually: run your own little mail server for all your family/friends conversations.

One major problem though is what to do with e-mails that are to be sent to recipients that are part of your toxmail contact list, but also to recipients that are not using Toxmail. I guess the best thing to do is to fallback to the regular routing in that case, and let the user know.

Anyways, lots of fun playing with this on my spare time.

The prototype is being built here, using Python and the PyTox binding:

https://github.com/tarekziade/toxmail

It has reached a state where you can actually send and receive e-mails :)

I'd love to have feedback on this little project.

[afpyro] AFPyro à Berlin - Vendredi 25 Juillet

Publié le 2014-07-25 00:00:00

Fr

A l’occasion d’EuroPython, venez transpirer au Sanatorium23 [et non Yaam] en dégustant une bonne bière fraiche

Départ groupé à 19h devant le BCC

En

The french python community is organising a non official meetup at Sanatorium23 [not Yaam] on friday. Come an meet us while tasting a fresh beer and dancing

A group will start at 7pm from the BCC

[gvaroquaux] The 2014 international scikit-learn sprint

Publié le 2014-07-24 22:59:58
A week ago, the 2014 edition of the scikit-learn sprint was held in Paris. This was the third time that we held an internation sprint and it was hugely productive, and great fun, as always. Great people and great venues We had a mix of core contributors and newcomers, which is a great combination, as it enables [...]

[rcommande] Papaye: le clone de PyPi

Publié le 2014-07-24 22:00:00
Papaya de ramyo, sur Flickr

Aujourd'hui, je vais vous parler d'un petit projet que je viens de mettre sur les rails. Je l'ai nommé Papaye, comme l'illustration ci-dessus, mais je ne suis pas certain que cela vous aide vraiment à savoir de quoi il s'agit.

C'est tout simplement d'une ré-implémentation du dépôt officiel de modules Python (PyPI pour "Python Packages Index"). Le but étant d'avoir son propre dépôt (sur sa machine ou sur son réseau) et d'y stocker des modules qui n'ont rien à faire sur le dépôt officiel, comme des modules construits par l'intégration continue, pas encore prêt à être diffusés ou tout simplement privés (souvent le cas en entreprise). L'avantage, c'est que l'on conservera toute la puissance de "PIP" pour l'installation !

Autre avantage de l'outil c'est de pouvoir travailler en local et installer des modules sans dépendre du réseau. Et oui, Papaye fait également office de proxy et de cache pour PyPI !

Implémenter ce genre de dépôt n'a vraiment rien de très complexe, d'autant que la majorité de l'intelligence ce situe côté client (via la commande "pip"). De plus, il existe tout un tas de projets similaires (localshop, pypiserver, pyshop, etc...) mais aucun ne correspondait vraiment à ce que je cherchai. J'ai dans un premier temps pensé à contribuer ou "forker" les projets existants, mais j'avais finalement une vision un peu différente des projets que j'avais sous les yeux (l'impression que je pourrai répondre à mon besoin de façon plus simple) et j'avais envie d'un peu ... d'expérimentations! J'ai finalement décidé de commencer le mien "from scratch".

Pourquoi "Papaye" ?

Comme d'habitude, une jeux de mot "tout pourri". Le dépôt officiel s'appelant "PyPI" et étant assez mauvais en anglais et ne n'ai absolument aucune idée de comment cela ce prononce. J'ai remarqué que beaucoup de francophone ont tendance à dire "PaïPaï", certainement parce que "pipi", ce n'est pas génial. Alors, finalement, "Papaye", ça y ressemble beaucoup et il y a une vraie signification en français. J'aime bien l'idée de dire que c'est pareil que le dépôt officiel, mais finalement, un peu différent.

Et puis "Papaye" c'est parfait. Un point c'est tout !

Objectifs

Avant de réaliser ce petit bricolage, voici les objectifs que je me suis fixés :

  • être le plus simple possible à mettre en place. Si possible, que du Python et tout installable via la commande "PIP". Je ne voulais vraiment pas qu'un utilisateur se tape un manuel d'installation de 45 pages pour installer l'outil sachant que je voulais qu'on puisse utiliser l'application aussi bien depuis un serveur qu'en local sur son poste. Je n'aurais pas supporté de perdre patience lors de la mise en place de ma propre application !
  • ne dépendre d'aucun service externe. Donc toute sorte de bases de données sous forme de service à démarrer et à configurer avant d'installer l'application n'est pas envisageable. Tous le monde ne sait pas comment cela fonctionne.
  • tout doit se lancer en une seule ligne de commande. Je passe mon temps à taper plein de commandes en tout genre tout au long de la journée, une seule pour lancer l'application ça suffit largement !
  • faire office de proxy vers le dépôt officiel. Comme ça je fais toujours pointer les fichiers de configuration de "PIP" vers mon instance Papaye qui, elle, redispatchera au bon endroit, c'est beaucoup moins prise de tête à gérer.
  • faire office de cache local pour le dépôt officiel. Une panne réseau ? PyPI non disponible ? On continue de bosser !
  • tailler pour des dépôt de petite et moyenne taille. Pour le moment, ne soyons pas trop ambicieux .

Présentation technique

Là encore, rien de bien compliqué :

  • Python. À bon ? Cela vous surprend toujours ?
  • Pyramid. Mon framework web favoris. J'aime vraiment beaucoup ce framework, mais je n'avais jamais eu l'occasion de mener un projet de bout en bout avec (le syndrome du "projet perso", le projet qu'on commence, qui révolutionnera le monde mais, qui ne sortira jamais par manque de temps :-p). Au boulot, c'est plutôt Django.
  • ZODB. La base de données NOSQL assez surprenante qui permet de stocker des objets Python directement. C'est ce que j'ai trouvé de plus simple et de plus pythonique pour faire du traversal avec Pyramid. Si le mode traversal ne vous dit rien, je vous invite à lire la documentation de Pyramid à ce sujet. C'est vraiment une façon intéressante de concevoir une application web qui tranche radicalement avec l'url dispatch. Les deux méthodes sont combinées dans Papaye.
  • Beaker. Pour mettre en cache les réponses venant du dépôt officiel.

Installation

Comment installer et faire tourner Papaye en quelques commandes :

pip install papaye
wget https://raw.githubusercontent.com/rcommande/papaye/master/production.ini
papaye_init production.ini
pserve production.ini

il ne reste plus qu'à vérifier que le serveur nous réponde (par défaut, à l'adresse http://localhost:6543/simple)

On peut maintenant l'utiliser avec PIP :

pip install -i http://localhost:6543/simple numpy

C'est tout de même plus pratique de configurer le dépôt de façon définitive plutôt que de devoir le préciser à chaque fois. Ça se passe dans le fichier ~/pip.conf. Il suffit d'ajouter la ligne suivante :

[install]
index-url = http://localhost:6543/simple

Ensuite, pour pouvoir envoyer vos modules dans votre instance Papaye, il faut éditer le fichier ~/.pypirc :

[distutils]
index-servers =
    papaye

[papaye]
username: <admin>
password: <password>
repository: http://localhost:6543/simple

Et pour finir, pour envoyer notre module sur le dépôt :

cd /chemin/vers/votre/module
python setup.py sdist upload -v -r papaye

Conclusion

Pour le moment seul l'interface "simple" a été implémenté. Ce n'est pas super sexy mais c'est le minimum pour pouvoir fonctionner avec PIP et Setuptools. En revanche, les fonctions de recherche (commande "pip search <pattern>) ne fonctionneront pas (j'ai manqué d'avoir une crise cardiaque quand j'ai vu que "PIP" communiquait avec le dépôt officiel en XML-RPC ...).

La prochaine étape, c'est une interface pour pouvoir naviguer dans les modules, car, pour le moment, c'est un peu une boite noire et ça ne vend pas du rêve.

Voilà pour mon petit projet du moment. Surtout n'hésitez pas à me faire parvenir vos retours / critiques / contributions / idées / cadeaux / bisous (rayer les mentions inutiles).

Plus d'infos ? C'est par ici

[logilab] EP14 Pylint sprint Day 1 report

Publié le 2014-07-24 14:51:00
https://ep2014.europython.eu/static_media/assets/images/logo.png

We've had a fairly enjoyable and productive first day in our little hidden room at EuroPython in Berlin ! Below are some noticeable things we've worked on and discussed about.

First, we discussed and agreed that while we should at some point cut the cord to the logilab.common package, it will take some time notably because of the usage logilab.common.configuration which would be somewhat costly to replace (and is working pretty well). There are some small steps we should do but basically we should mostly get back some pylint/astroid specific things from logilab.common to astroid or pylint. This should be partly done during the sprint, and remaining work will go to tickets in the tracker.

We also discussed about release management. The point is that we should release more often, so every pylint maintainers should be able to do that easily. Sylvain will write some document about the release procedure and ensure access are granted to the pylint and astroid projects on pypi. We shall release pylint 1.3 / astroid 1.2 soon, and those releases branches will be the last one supporting python < 2.7.

During this first day, we also had the opportunity to meet Carl Crowder, the guy behind http://landscape.io, as well as David Halter which is building the Jedi completion library (https://github.com/davidhalter/jedi). Landscape.io runs pylint on thousands of projects, and it would be nice if we could test beta release on some part of this panel. On the other hand, there are probably many code to share with the Jedi library like the parser and ast generation, as well as a static inference engine. That deserves a sprint on his own though, so we agreed that a nice first step would be to build a common library for import resolution without relying on the python interpreter for that, while handling most of the python dark import features like zip/egg import, .pth files and so one. Indeed that may be two nice future collaborations!

Last but not least, we got some actual work done:

  • Michal Nowikowski from Intel in Poland joined us to work on the ability to run pylint in different processes so it may drastically improve performance on multiple cores box.
  • Torsten did continue some work on various improvements of the functionnal test framework.
  • Sylvain did merge logilab.common.modutils module into astroid as it's mostly driven by astroid and pylint needs. Also fixed the annoying namespace package crash.
  • Claudiu keep up the good work he does daily at improving and fixing pylint :)

[Biologeek] Lecture et joie

Publié le 2014-07-20 11:00:00

Je ne milite en aucun cas pour l’abolition de l’école. Je crois, effectivement, qu’il serait catastrophique, en l’état actuel des choses, de la supprimer. Je pense, effectivement, qu’il y a de nombreux parents qui ne pourraient, ne voudraient ou ne sauraient en aucun cas assumer cette nouvelle condition ; je pense, effectivement, que la situation actuelle de nombreuses personnes rendrait irréaliste, voire périlleuse, la non-scolarisation de leurs enfants.

Mais quid de tous ceux qui en ont la possibilité et, peut-être, le désir, mais qui l’ignorent ? C’est à eux que mon témoignage offre, je l’espère, l’inspiration pour une pensée nouvelle. Respecter ses convictions, faire, en toute conscience, des choix personnels, honorer son originalité, être l’artisan de son propre devenir : tout cela, bien davantage que l’endoctrinement des masses, contribue à la progression du monde et à l’apparition de nouveaux paradigmes.

… et je ne suis jamais allé à l’école, André Stern

J’ai terminé de lire … et je ne suis jamais allé à l’école à mon fils. Quelques pages quasiment chaque jour depuis 3 mois. La joie qu’il a manifesté lorsque j’ai sorti le livre les dernières fois m’a vraiment ému. Identifier le livre comme un moment de bonheur. Comme une vaine tentative de le dévorer littéralement aussi :-).

Au fil des pages, je me suis rendu compte à quel point ma lecture à voix haute a changée, une meilleure continuité, une meilleure gestion des liaisons, des différentes voix des personnages. Essayer de rendre la forme aussi intéressante que le fond a été un exercice quotidien, pour une lecture plus lente, plus détaillée, plus profonde. La prose d’André Stern se prête bien à une telle lecture et le propos est lucide et sensé, ça donne des idées…

Prochaine lecture : Libres enfants de Summerhill.

[gvaroquaux] Scikit-learn 0.15 release: lots of speedups!

Publié le 2014-07-15 13:25:57
We have just released the 0.15 version of scikit-learn. Hurray!! Thanks to all involved. A long development stretch It’s been a while since the last release of scikit-learn. So a lot has happened. Exactly 2611 commits according my count. Quite clearly, we have more and more existing code, more and more features to support. This means that when [...]

[logilab] PyLint sprint during EuroPython in Berlin

Publié le 2014-07-11 12:51:00

The three main maintainers/developpers of Pylint/astroid (Claudiu, Torsten and I) will meet together in Berlin during EuroPython 2014. While this is not an "official" EuroPython sprint but it's still worth announcing it since it's a good opportunity to meet and enhance Pylint. We should find place and time to work on Pylint between wednesday 23 and friday 25.

If you're interested, don't hesitate to contact me (sylvain.thenault@logilab.fr / @sythenault).

[cubicweb] CubicWeb roadmap meeting on July 3rd, 2014

Publié le 2014-07-07 14:18:00

The Logilab team holds a roadmap meeting every two months to plan its CubicWeb development effort. The previous roadmap meeting was in May 2014.

Here is the report about the July 3rd, 2014 meeting. Christophe de Vienne (Unlish) and Dimitri Papadopoulos (CEA) joined us to express their concerns and discuss the future of CubicWeb.

Versions

Version 3.17

This version is stable but old and maintainance will continue only as long as some customers will be willing to pay for it (current is 3.17.15 with 3.17.16 in development).

Version 3.18

This version is stable and maintained (current is 3.18.5 with 3.18.6 in development).

Version 3.19

This version was published at the end of April and has now been tested on our internal servers. It includes support for Cross Origin Resource Sharing (CORS) and a heavy refactoring that modifies sessions and sources to lay the path for CubicWeb 4.

For details read the release notes or the list of tickets for CubicWeb 3.19.0. Current is 3.19.2

Version 3.20

This version is under development. It will try to reduce as much as possible the stock of patches in the state "reviewed", "awaiting review" and "in progress". If you have had something in the works that has not been accepted yet, please ready it for 3.20 and get it merged.

It should still include the work done for CWEP-002 (computed attributes and relations.

For details read list of tickets for CubicWeb 3.20.0.

Version 3.21 (or maybe 4.0?)

Removal of the dbapi, merging of Connection and ClientConnection, CWEP-003 (adding a FROM clause to RQL).

Cubes

Cubes published over the past two months

New cubes

  • cubicweb-frbr: Cube providing a schema based on FRBR entities
  • cubicweb-clinipath
  • cubicweb-fastimport

CWEPs

Here is the status of open CubicWeb Evolution Proposals:

CWEP-0002 only missing a bit of migration support, to be finished soon for inclusion in 3.20.

CWEP-0003 has been reviewed and is waiting for a bit of reshaping that should occurs soon. It's targeted for 3.21.

New CWEPs are expected to be written for clarifying the API of the _cw object, supporting persistent sessions and improving the performance of massive imports.

Work in progress

Design

The new logo is now published in the 3.19 line. David showed us his experimentation that modernize a forge's ui with a bit of CSS. There is still a bit of pressure on the bootstrap side though, as it still rely on heavy monkey-patching in the cubicweb-bootstrap cube.

Data import

Also, Dimitry expressed is concerns with the lack of proper data import API. We should soon have some feedback from Aurelien's cubicweb-fastimport experimentation, which may be an answer to Dimitry's need. In the end, we somewhat agreed that there were different needs (eg massive-no-consistency import vs not-so-big-but-still-safe), that cubicweb.dataimport was an attempt to answer them all and then cubicweb-dataio and cubicweb-fastimport were more specific responses. In the end we may reasonably hope that an API will emerge.

Removals

On his way to persistent sessions, Aurélien made a huge progress toward silence of warnings in the 3.19 tests. dbapi has been removed, ClientConnection / Connection merged. We decided to take some time to think about the recurring task management as it is related to other tricky topics (application / instance configuration) and it's not directly related to persistent session.

Rebasing on Pyramid

Last but not least, Christophe demonstrated that CubicWeb could basically live with Pyramid. This experimentation will be pursued as it sounds very promising to get the good parts from the two framework.

Agenda

Logilab's next roadmap meeting will be held at the beginning of september 2014 and Christophe and Dimitri were invited.

[logilab] Nazca notebooks

Publié le 2014-07-07 12:44:00

We have just published the following ipython notebooks explaining how to perform record linkage and entities matching with Nazca:

[tarek] NGinxTest

Publié le 2014-06-29 09:40:00

I've been playing with Lua and Nginx lately, using the OpenResty bundle.

This bundle is an Nginx distribution on steroids, that includes some extensions and in particular the HTTPLuaModule which let you script Nginx using the Lua programming language.

Coming from a Python background, I was quite pleased with the Lua syntax, which feels like a cleaner Javascript inspired from Pascal and Python - if that even makes any sense :)

Here's how a Lua function look like:

-- rate limiting
function rate_limit(remote_ip, stats)
    local hits = stats:get(remote_ip)
    if hits == nil then
        stats:set(remote_ip, 1, throttle_time)
        return false
    end

    hits = hits + 1
    stats:set(remote_ip, hits, throttle_time)
    return hits >= max_hits
end

Peformance-wise, interacting with incoming web requests in Lua co-routines in Nginx is blazing fast. And there are a lot of work that can be done there to spare your proxied Python/Node.js/Go/Whatever application some cycles and complexity.

It can also help you standardize and reuse good practices across all your web apps no matter what language/framework they use.

Some things that can be done there:

  • web application firewalling
  • caching
  • dynamic routing
  • logging, load balancing
  • a ton of other pre-work...

To put it simply:

Nginx become very easy to extend with Lua scripting without having to re-compile it all the time, and Lua lowers the barrier for ops and developers to implement new server behaviors.

Testing with Test::Nginx

When you start to add some Lua scripting in your Nginx environment, testing soon become mandatory. Pure unit testing Lua scripts in that context is quite hard because you are interacting with Nginx variables and functions.

The other approach is doing only pure functional tests by launching Nginx with the Lua script loaded, and interacting with the server using an HTTP client.

OpenResty offers a Perl tool to do this, called Test::Nginx where you can describe in a light DSL an interaction with the NGinx server.

Example from the documentation:

# foo.t
use Test::Nginx::Socket;
repeat_each(1);
plan tests => 2 * repeat_each() * blocks();
$ENV{TEST_NGINX_MEMCACHED_PORT} ||= 11211;  # make this env take a default value
run_tests();

__DATA__

=== TEST 1: sanity
--- config
location /foo {
    set $memc_cmd set;
    set $memc_key foo;
    set $memc_value bar;
    memc_pass 127.0.0.1:$TEST_NGINX_MEMCACHED_PORT;
}
--- request
    GET /foo
--- response_body_like: STORED
--- error_code: 201

The data section of the Perl script describes the Nginx configuration, the request made and the expected response body and status code.

For simple tests it's quite handy, but as soon as you want to do more complex tests it becomes hard to use the DSL. In my case I needed to run a series of requests in a precise timing to test my rate limiting script.

I missed my usual tools like WebTest, where you can write plain Python to interact with a web server.

Testing with NginxTest

Starting and stopping an Nginx server with a specific configuration loaded is not hard, so I started a small project in Python in order to be able to write my tests using WebTest.

It's called NGinxTest and has no ambitions to provide all the features the Perl tool provides, but is good enough to write complex scenarios in WebTest or whatever Python HTTP client you want in a Python unit test class.

The project provides a NginxServer class that takes care of driving an Nginx server.

Here's a full example of a test using it:

import os
import unittest
import time

from webtest import TestApp
from nginxtest.server import NginxServer

LIBDIR = os.path.normpath(os.path.join(os.path.dirname(__file__),
                        '..', 'lib'))
LUA_SCRIPT = os.path.join(LIBDIR, 'rate_limit.lua')

_HTTP_OPTIONS = """\
lua_package_path "%s/?.lua;;";
lua_shared_dict stats 100k;
""" % LIBDIR


_SERVER_OPTIONS = """\
set $max_hits 4;
set $throttle_time 0.3;
access_by_lua_file '%s/rate_limit.lua';
""" % LIBDIR


class TestMyNginx(unittest.TestCase):

    def setUp(self):
        hello = {'path': '/hello', 'definition': 'echo "hello";'}
        self.nginx = NginxServer(locations=[hello],
                                http_options=_HTTP_OPTIONS,
                                server_options=_SERVER_OPTIONS)
        self.nginx.start()
        self.app = TestApp(self.nginx.root_url, lint=True)

    def tearDown(self):
        self.nginx.stop()

    def test_rate(self):
        # the 3rd call should be returning a 429
        self.app.get('/hello', status=200)
        self.app.get('/hello', status=200)
        self.app.get('/hello', status=404)

    def test_rate2(self):
        # the 3rd call should be returning a 200
        # because the blacklist is ttled
        self.app.get('/hello', status=200)
        self.app.get('/hello', status=200)
        time.sleep(.4)
        self.app.get('/hello', status=200)

Like the Perl script, you provide bits of configuration for your Nginx server -- in this case pointing the Lua script to test and some general configuration.

Then I test my rate limiting feature using Nose:

$ bin/nosetests -sv tests/test_rate_limit.py
test_rate (test_rate_limit.TestMyNginx) ... ok
test_rate2 (test_rate_limit.TestMyNginx) ... ok

----------------------------------------------------------------------
Ran 2 tests in 1.196s

OK

Out of the 1.2 seconds, the test sleeps half a second, and the class starts and stops a full Nginx server twice. Not too bad!

I have not released that project at PyPI - but if you think it's useful to you and if you want some more features in it, let me know!

[tarek] Decentralization Mailing List

Publié le 2014-06-27 14:20:00

This is long time due !

Following up with my previous blog post I have started a Decentralization Mailing list.

The goal of this mailing list is to discuss technologies related to data decentralization in Mozilla projects - and in particular in the ones we work at in the Cloud Services team (but it can go beyond of course)

A few topic examples that people brought up:

  1. Could remoteStorage be used with Firefox Account to build Firefox OS apps where people can store their own data ?
  2. Can Firefox Sync use a remoteStorage backend ?
  3. Why can't I run a simple "apt-get install firefox-sync" and host my own server ?
  4. What about peer-to-peer ? How does that fit with the services we provide ?

The list is at : https://lists.mozilla.org/listinfo/dev-decentralization

I will wait a week or so to launch topics there, but if you are interested in this topic, if you want to lurk or to launch an idea - please join.

On my side, the first topic I will probably talk about in this ML is #1.

[afpyro] AFPyro à Lyon - mercredi 25 juin

Publié le 2014-06-25 00:00:00

Un Afpyro aura lieu le mercredi 25 juin à partir de 20h à l’Antre Autre - 11 rue Terme - 69001 Lyon.

Cette soirée aura pour thème Docker avec deux présentations :

  • Docker 101 par Geoffrey Bachelet
  • Docker et Python par Haïkel Guémar

L’Antre Autre est un lieu où nous pouvons discuter autour d’un verre, et, pour ceux qui le souhaitent, prendre un repas.

Pour se rendre à l’Antre Autre :

  • en métro : arrêt Hôtel de Ville
  • en bus : lignes C13 et C18 arrêt Mairie du 1er ou lignes 19, C14 et C3 à l’arrêt Terreaux
  • en vélo’v : stations Place Sathonay, Carmélites Burdeau, Place de la paix

[Biologeek] Éducation et informatique

Publié le 2014-06-23 11:00:00

Moins les enfants regarderont les écrans, plus ils développeront leur imagination et leur créativité. Car les écrans contiennent en eux des histoires visuelles et sonores qui empêcheraient les enfants d’imaginer d’autres images et d’autres mondes possibles.

Écran global, reportage de Anne-Sophie Lévy-Chambon

Protéger son enfant des écrans s’avère être une tâche plus difficile que ce que j’imaginais. Le compteur en cumulé doit être aux alentours des 10-15 minutes après 7 mois, ce qui est plutôt dans la limite haute de ce que je m’étais fixé. Et lorsque je vois l’attrait qu’il a pour un écran dès qu’il en croise un, cela me conforte dans l’idée qu’il va falloir attendre qu’il soit en mesure de comprendre un peu ce qu’il y a derrière : une fenêtre déshumanisée sur l’Humanité.

On parle souvent de la limite des 3 ans pour qu’un enfant puisse regarder/interagir avec un écran sans être perturbé par l’absence de retour de sa part. On verra à ce moment là si mon digital native souhaite faire usage de ses doigts.

L’élève sait que les équipements informatiques utilisent une information codée et il est initié au fonctionnement, au processus et aux règles des langages informatiques ; il est capable de réaliser de petites applications utilisant des algorithmes simples.

Socle commun de connaissances, de compétences et de culture

Damien B et Éric D. discutaient ce soir de l’apprentissage du code en primaire sur Twitter. J’ai beaucoup de mal avec cette question car le code constitue une part non négligeable de mon quotidien et de mon métier. Et si je trouve que la connaissance du Web devrait faire partie de l’éducation citoyenne, je suis plus circonspect sur le développement en lui-même. En fait, il s’agit d’une problématique de cohérence. Soit on considère que le codage (sic) est une activité artisanale et dans ce cas il faudrait également enseigner d’autres activités comme le travail du bois en primaire (ce que certaines écoles alternatives font — voir le reportage sus-cité). Soit on considère que l’industrialisation de l’informatique est inévitable et dans ce cas là toute la question algorithmique simple devient inutile puisqu’il s’agira d’empiler les boîtes noires à un autre niveau. Il faut bien définir les objectifs que l’on se fixe avec cet apprentissage du code dès le primaire. Dans quelle mesure permet-il la poursuite d’études, la construction d’un avenir personnel et professionnel et préparer à l’exercice de la citoyenneté ? Tous bidouilleurs, soit, mais que nous laisse-t-on bidouiller par la suite ?

Ce que je vois en filigrane de cette mutation est plus grave, c’est la mise sur un piédestal de ceux qui savent coder par pure incompréhension du changement de paradigme qui est en train de s’effectuer avec le numérique. Ou serait-ce pour pouvoir à terme alimenter plus facilement les canons publicitaires ? La question reste ouverte… jusqu’à la prochaine réforme.

[logilab] Tester MPI avec CMake et un framework de test comme Boost

Publié le 2014-06-20 12:12:00

Objectif

Compiler et exécuter un fichier de test unitaire avec MPI.

Je suppose que :

  • une implémentation de MPI est installée (nous prendrons OpenMPI)
  • les bibliothèques Boost MPI et Boost Unit Test Framework sont présentes
  • vous connaissez quelques rudiments de CMake

CMake

On utilise le bien connu find_package pour Boost et MPI afin de récupérer tout ce qu'il nous faut pour les headers et les futurs links.

find_package (MPI REQUIRED)
find_package (Boost COMPONENTS mpi REQUIRED)

# Boost dirs for headers and libs.
include_directories (SYSTEM ${Boost_INCLUDE_DIR})
link_directories (${Boost_LIBRARY_DIRS})

Par la suite, on a essentiellement besoin des variables CMake :

  • Boost_MPI_LIBRARY pour le link avec Boost::MPI
  • MPI_CXX_LIBRARIES pour le link avec la bibliothèque OpenMPI
  • MPIEXEC qui nous donne la commande pour lancer un exécutable via MPI

On prend un fichier example_mpi.cpp (des exemples simples sont faciles à trouver sur la Toile). Pour le compiler, on fait :

set(CMAKE_CXX_COMPILER mpicxx)

# MPI example.
add_executable(example_mpi example_mpi.cpp)
target_link_libraries(example_mpi ${MPI_CXX_LIBRARIES})

voire juste

target_link_libraries(example_mpi ${Boost_MPI_LIBRARY})

si on décide d'utiliser la bibliothèque Boost MPI.

Note

mpicxx est une commande qui enrobe le compilateur (g++ par exemple). On dit à CMake d'utiliser mpicxx au lieu du compilo par défaut.

Note

Boost::MPI n'est pas une implémentation de MPI. C'est une bibliothèque plus haut niveau qui s'abstrait de l'implémentation de MPI. Il faut nécessairement en installer une (OpenMPI, LAM/MPI, MPICH2, ...).

L'exemple peut très simplement ressembler à :

#include <boost/mpi/environment.hpp>
#include <boost/mpi/communicator.hpp>
#include <iostream>

namespace mpi = boost::mpi;

int main()
{
  mpi::environment env;
  mpi::communicator world;
  std::cout << "I am process " << world.rank() << " of " << world.size()
            << "." << std::endl;
  return 0;
}

Exécuter

Une fois la compilation effectuée, faire simplement :

> mpiexec -np 4 ./example_mpi

pour lancer l'exécutable sur 4 cœurs.

Problème : mais pourquoi tu testes ?

On veut pouvoir faire des exécutables qui soient de vrais tests unitaires et non pas un exemple avec juste une fonction main. De plus, comme j'utilise CMake, je veux pouvoir automatiser le lancement de tous mes exécutables via CTest.

Problème : il faut bien initialiser et bien dire à MPI que j'en ai fini avec toutes mes MPI-series.

En "vrai" MPI, on a :

int main(int argc, char* argv[])
{
  MPI_Init(&argc, &argv);

  int rank;
  MPI_Comm_rank(MPI_COMM_WORLD, &rank);
  // Code here..
  // ... and here
  MPI_Finalize();

  return 0;
}

Note

C'est ce que fait le constructeur/destructeur de boost::mpi::environment.

En d'autres termes, je veux me faire ma propre fonction main pour l'initialisation de tous mes cas tests Boost (ou avec n'importe quel autre framework de test unitaire C/C++).

La documentation de Boost Unit Test, que je trouve parfois très peu claire avec un manque cruel d'exemple, m'a fait galérer quelques heures avant de trouver quelque chose de simple qui fonctionne.

Conseil : aller regarder les exemples des sources en faisant quelques grep est parfois plus efficace que de trouver la bonne info dans la doc en ligne. On peut aussi en lire sur https://github.com/boostorg/test/tree/master/example

Deux solutions :

  1. la première que j'ai trouvée dans les tests de Boost::MPI lui-même. Ils utilisent le minimal testing facility. Mais seule la macro BOOST_CHECK est utilisable. Et oubliez les BOOST_CHECK_EQUAL ainsi que l'enregistrement automatique de vos tests dans la suite de tests.
  2. la deuxième redéfinit la fonction main et appelle boost::unit_test::unit_test_main sans définir ni la macro BOOST_TEST_MODULE ni BOOST_TEST_MAIN qui impliquent la génération automatique de la fonction main par le framework de test (que l'on compile en statique ou dynamique). Pour plus de détails, lire http://www.boost.org/doc/libs/release/libs/test/doc/html/utf/user-guide/test-runners.html

J'utiliserai la deuxième solution.

Note

Ne pensez même pas faire une fixture Boost pour y mettre votre boost::mpi::environment puisque cette dernière sera construite/détruite pour chaque cas test (équivalent du setUp/tearDown). Et il est fort probable que vous ayez ce genre d'erreur :

*** The MPI_Errhandler_set() function was called after MPI_FINALIZE was invoked.
*** This is disallowed by the MPI standard.
*** Your MPI job will now abort.
[hostname:11843] Abort after MPI_FINALIZE completed successfully; not able to guarantee that all other processes were killed!

Un exemple qui marche

On souhaite ici tester que le nombre de procs passés en argument de mpiexec est au moins 2.

Le BOOST_TEST_DYN_LINK dit juste que je vais me lier dynamiquement à Boost::Test.

#define BOOST_TEST_DYN_LINK
#include <boost/test/unit_test.hpp>

#include <boost/mpi/environment.hpp>
#include <boost/mpi/communicator.hpp>

namespace mpi = boost::mpi;

BOOST_AUTO_TEST_CASE(test_check_world_size)
{
    mpi::communicator world;
    BOOST_CHECK(world.size() > 1);
}


// (empty) Initialization function. Can't use testing tools here.
bool init_function()
{
    return true;
}

int main(int argc, char* argv[])
{
    mpi::environment env(argc, argv);
    return ::boost::unit_test::unit_test_main( &init_function, argc, argv );
}

On lance tout ça avec un joli mpiexec -np 2 ./test_mpi et on est (presque) content.

Et un peu de CTest pour finir

Une dernière chose : on aimerait dire à CMake via CTest de lancer cet exécutable, mais avec mpiexec et les arguments qui vont bien.

Un cmake --help-command add_test nous indique qu'il est possible de lancer n'importe quel exécutable avec un nombre variable d'arguments. On va donc lui passer : /usr/bin/mpiexec -np NB_PROC ./test_mpi.

Un œil au module FindMPI.cmake nous dit aussi qu'on peut utiliser d'autres variables CMake MPI pour ce genre de chose.

Reprenons donc notre fichier CMake et ajoutons :

add_executable(test_mpi test_mpi.cpp)
target_link_libraries(test_mpi ${Boost_MPI_LIBRARY})
# Number of procs for MPI.
set (PROCS 2)
# Command to launch by CTest. Need the MPI executable and the number of procs.
add_test (test_mpi ${MPIEXEC} ${MPIEXEC_NUMPROC_FLAG} ${PROCS}
   ${MPIEXEC_PREFLAGS}
   test_mpi
   ${MPIEXEC_POSTFLAGS})

où mon exécutable et mon test porte le même nom : test_mpi. On lance le tout avec la commande ctest dans notre dossier de build et hop, le tour est joué !

[afpyro] AFPyro à Pau - Jeudi 19 Juin

Publié le 2014-06-19 00:00:00

Un Afpyro aura lieu le Jeudi 19 Juin à partir de 20h au Fablab de Pau

Venez rencontrer et échanger avec la comunauté pythoniste paloise en vous délectant de succulant breuvages!

Fablab

4 rue despourrins

64000 PAU

Voir la map

[sciunto] Utiliser pyserial pour dialoguer avec une balance et un port série

Publié le 2014-06-10 22:00:00

Dans mon billet précédent, je présentais une méthode permettant d'obtenir la valeur d'un afficheur à partir d'une prise de photos et d'un traitement d'images suivis d'un machine-learning.

Je passe maintenant au cas où l'appareil est doté d'un port série et de la documentation qui va avec. Je connecte donc ma machine à un adapatateur usb/série et le device apparait dans /dev/ttyUSB0.

On sort python et sa bibliothèque pyserial. Je souhaite ici récupérer la masse en fonction du temps d'une balance Mettler Toledo XS105. Dans la doc, je sais que je dois envoyer la commande 'SI' et que la balance me répondra (même si elle n'est pas stable, cf doc).

Je commence par écrire une petite fonction qui va me récupérer tout ça.

#!/usr/bin/env python2
# -*- coding: utf-8 -*-
# License: GPLv3

# Parameters for the Mettler Toledo XS105 scale:
# 9600
# 8/No
# 1 stopbit
# Xon/Xoff
# <CR><LF>
# Ansi/win
# Off

import serial
import time
import re


def read_weight(socket, timelapse=1):
    """
    Returns the weight in gram and the stability.

    :param socket: serial socket
    :param timelapse: timelapse between each measurement
    :returns: tuple (weight, stability)
    """
    ser.write('\nSI\n')
    time.sleep(1)
    value = ser.read(ser.inWaiting())
    value = value.split('\n')[1][:-1]
    if value[3] == 'S':
        stability = True
    else:
        stability = False
    weight = value[4:-1].strip(' ')
    return (weight, stability)

Ensuite, je procède à l'ouverture d'une socket avec les options que j'ai configuré dans la balance, puis je boucle sur ma fonction pour récupérer régulièrement la masse. Le programme se termine avec un Ctrl-C.

if __name__ == '__main__':

    ser = serial.Serial(port='/dev/ttyUSB0',
                        baudrate=9600,
                        parity=serial.PARITY_NONE,
                        stopbits=serial.STOPBITS_ONE,
                        bytesize=serial.EIGHTBITS
    )

    if not ser.isOpen():
        ser.open()
    with open('data.dat', 'w') as fh:
        fh.write('# Time (s) | Weight (g) | Stability')
        zerotimer = time.time()  # perf_counter might be better py3
        try:
            while True:
                weight, stability = read_weight(ser)
                timer = time.time() - zerotimer
                print('t = ' + str(timer) + 's | M = ' + str(weight) + ' g')
                fh.write(str(timer) + ' ' + weight + ' ' + str(stability) +'\n')
        except KeyboardInterrupt:
            fh.close()

Et voilà !

[logilab] Open Legislative Data Conference 2014

Publié le 2014-06-10 15:57:00

I was at the Open Legislative Data Conference on may 28 2014 in Paris, to present a simple demo I worked on since the same event that happened two years ago.

The demo was called "Law is Code Rebooted with CubicWeb". It featured the use of the cubicweb-vcreview component to display the amendments of the hospital law ("loi hospitalière") gathered into a version control system (namely Mercurial).

The basic idea is to compare writing code and writing law, for both are collaborative and distributed writing processes. Could we reuse for the second one the tools developed for the first?

Here are the slides and a few screenshots.

http://www.logilab.org/file/253394/raw/lawiscode1.png

Statistics with queries embedded in report page.

http://www.logilab.org/file/253400/raw/lawiscode2.png

List of amendments.

http://www.logilab.org/file/253396/raw/lawiscode3.png

User comment on an amendment.

While attending the conference, I enjoyed several interesting talks and chats with other participants, including:

  1. the study of co-sponsorship of proposals in the french parliament
  2. data.senat.fr announcing their use of PostgreSQL and JSON.
  3. and last but not least, the great work done by RegardsCitoyens and SciencesPo MediaLab on visualizing the law making process.

Thanks to the organisation team and the other speakers. Hope to see you again!

[sciunto] Détection de nombres d'un afficheur avec scikit-image et scikit-learn

Publié le 2014-06-07 22:00:00

Dans ce billet, je propose de traiter le problème suivant. Prenons le cas d'un appareil possédant un afficheur digital tel qu'une balance, un voltmètre, un réveil, un hygromètre... mais ne possédant pas de moyen simple de récupérer les données (absence de port série etc). Si on souhaite collecter les données, deux méthodes s'offrent à nous. La première est celle de l'électronicien qui consiste à mettre un moyen de communication là où il n'y en a pas. L'inconvénient est qu'il faut avoir une compétence (que je n'ai pas) et qu'il faut faire du cas par cas. La seconde technique est de prendre en photo l'afficheur et d'analyser les images. C'est ce qu'on va faire ici.

Pour la démonstration, je vais utiliser python, une balance dont la masse affichée fluctue au cours du temps et les photos de l'afficheur.

Une fois le lot de photos sur le disque (ex: Img0001.png), on va chercher à détecter les chiffres (ou digits). Scikit-image va nous être précieux. Il nous faut :

  • appliquer un seuil à l'image pour enlever les parasites et passer en binaire. Otsu est intéressant car local, ce qui permet de se prémunir de variation de contraste à grande échelle.
  • connecter les morceaux dans le cas d'un afficheur 7 segments ou d'un seuillage trop agressif.
  • remplir les trous pour qu'il ne soit pas détecté comme objet
  • étiqueter les régions et ne considérer que celles supérieures à une taille critique
  • les extraire

Ceci est fait par ce code (qui manque encore de soin)

import os.path
import glob

import numpy as np
from scipy import ndimage
import matplotlib.pyplot as plt
import matplotlib.patches as mpatches

import skimage.io
from skimage.filter import threshold_otsu
from skimage.segmentation import clear_border
from skimage.morphology import closing, square
from skimage.measure import regionprops, label
from skimage.color import label2rgb


def segment_digit(image, filename, output_dir, digit_height=100, digit_width=52,
                  border=7, black_on_white=True, closingpx=4):
    """
    Segement each digit of a picture

    :param image: grey scale picture
    :param filename: filename of the picture source
    :param output_dir: path for the output
    :param digit_height: height of a digit
    :param digit_width: width of a digit
    :param border: pixels to shift the border
    :param black_on_white: black digit on clear background
    :param closingpx: number of pixels to close
    """
    # apply threshold
    thresh = threshold_otsu(image)
    if black_on_white:
        bw = closing(image > thresh, square(closingpx))
    else:
        bw = closing(image < thresh, square(closingpx))

    filled = ndimage.binary_fill_holes(bw)
    #plt.imshow(filled)
    #plt.show()

    # remove artifacts connected to image border
    cleared = filled.copy()
    clear_border(cleared)

    # label image regions
    label_image = label(cleared)
    borders = np.logical_xor(filled, cleared)
    label_image[borders] = -1
    image_label_overlay = label2rgb(label_image, image=image)

    fig, ax = plt.subplots(ncols=1, nrows=1, figsize=(6, 6))
    ax.imshow(image_label_overlay)

    regions = regionprops(label_image)

    for item, region in enumerate(regions):
        # skip small elements
        if region['Area'] < 300:
            continue

        # draw rectangle around segmented digits
        minr, minc, maxr, maxc = region['BoundingBox']
        rect = mpatches.Rectangle((minc, minr), maxc - minc, maxr - minr,
                                  fill=False, edgecolor='red', linewidth=2)

        # uniq size
        img = np.zeros((100, 75), 'uint8')
        img[bw[minr:maxr, minc:maxc]!=0] = 255
        newname = os.path.splitext(os.path.basename(filename))[0] + '-' + str(item) + '.png'
        skimage.io.imsave(os.path.join(output_dir, newname), img)
        ax.add_patch(rect)

    plt.show()
Segmentation de chaque digit

Segmentation de chaque digit

On s'est donc fabriqué un lot d'images (Img0001-0.png, Img0001-1.png...) correspondant à chaque digit.

Il nous reste maintenant à les identifier. Une première méthode serait de faire du template matching, mais ça peut vite s'avérer peu robuste. On va donc préférer passer par du machine-learning. Scikit-learn est là pour ça.

Le principe :

  • On identifie un sous lot d'images. Dans mon cas, j'ai identifié trois images pour chaque digit (donc 30) et elles sont nommées sous la forme digit-id.png).
  • On entraine l'algorithme sur ces images identifiées.
  • On demande de deviner les images inconnues.

Pour la partie connue :

import glob
import os

import numpy as np
import pylab as pl

from sklearn import svm, metrics
import skimage.io

def load_knowndata(filenames):
    training = {'images': [], 'targets': [], 'data' : [], 'name' : []}

    for index, filename in enumerate(filenames):
        target = os.path.splitext(os.path.basename(filename))[0]
        target = int(target.split('-')[0])
        image = skimage.io.imread(filename)
        training['targets'].append(target)
        training['images'].append(image)
        training['name'].append(filename)
        training['data'].append(image.flatten().tolist())
        pl.subplot(6, 5, index + 1)
        pl.axis('off')
        pl.imshow(image, cmap=pl.cm.gray_r, interpolation='nearest')
        pl.title('Training: %i' % target)

    ## To apply an classifier on this data, we need to flatten the image, to
    ## turn the data in a (samples, feature) matrix:
    n_samples = len(training['images'])
    training['images'] = np.array(training['images'])
    training['targets'] = np.array(training['targets'])
    training['data'] = np.array(training['data'])
    return training

Pour la partie inconnue :

def load_unknowndata(filenames):
    training = {'images': [], 'targets': [], 'data' : [], 'name' : []}

    for index, filename in enumerate(filenames):
        image = skimage.io.imread(filename)
        training['targets'].append(-1) # Target = -1: unkown
        training['images'].append(image)
        training['name'].append(filename)
        training['data'].append(image.flatten().tolist())

    ## To apply an classifier on this data, we need to flatten the image, to
    ## turn the data in a (samples, feature) matrix:
    n_samples = len(training['images'])
    training['images'] = np.array(training['images'])
    training['targets'] = np.array(training['targets'])
    training['data'] = np.array(training['data'])
    return training

et on écrit un main rapidement pour enchainer tout ça


if __name__ == '__main__':
    filenames = sorted(glob.glob('learn/*-*.png'))
    training = load_knowndata(filenames)
    pl.show()
    pl.close()

    # Create a classifier: a support vector classifier
    classifier = svm.SVC(gamma=1e-8)

    # We learn the digits on the first half of the digits
    classifier.fit(training['data'], training['targets'])

    filenames = sorted(glob.glob('data/*.png'))
    unknown = load_unknowndata(filenames)

    filenames = glob.glob('data/*.png')
    filenames = set([os.path.splitext(os.path.basename(fn))[0].split('-')[0] for fn in filenames])

    for filename in filenames:
        print('----')
        print(filename)
        print('----')
        fn = sorted(glob.glob('data/' + filename  + '*.png'))
        unknown = load_unknowndata(fn)
        # Now predict the value of the digit on the second half:
        #expected = digits.target[n_samples / 2:]
        predicted = classifier.predict(unknown['data'])

        result = ''
        for pred, image, name in zip(predicted, unknown['images'], unknown['name']):
            print(pred)
            print(name)
            result += str(pred)

        # Check
        fn = 'pictures/' + filename  + '.png'
        image = skimage.io.imread(fn)
        pl.imshow(image[:150, 56:], cmap=pl.cm.gray_r, interpolation='nearest')
        pl.title('Predicted: %s' % result)
        pl.show()

Le résultat est que sur des images de 150 par 300 pixels, contenant 5 digits chacune, j'ai eu 100% de succès sur un test de 60 images. L'algo est même robuste à un changement de valeur du dernier chiffre significatif de la balance lors de la prise de la photo qui se traduit par une superposition de deux digits sur la photos. L'algo détecte l'une ou l'autre des valeurs qu'un humain verrait.

detection de nombres avec une fluctuation : 24774

detection de nombres avec une fluctuation : 24774

En conclusion, on se retrouve avec un moyen simple de récupérer les valeurs de n'importe quel afficheur et sans effort ni bricolage.

[afpyro] AFPyro à Lyon - mercredi 28 mai

Publié le 2014-05-28 00:00:00

Un Afpyro aura lieu le mercredi 28 mai à partir de 20h à l’Antre Autre - 11 rue Terme - 69001 Lyon.

Une présentation sur Celery sera donnée. Celery est un gestionnaire de tâches qui permet de les traiter de manière asynchrone.

L’Antre Autre est un lieu où nous pouvons discuter autour d’un verre, et, pour ceux qui le souhaitent, prendre un repas.

Pour se rendre à l’Antre Autre :

  • en métro : arrêt Hôtel de Ville
  • en bus : lignes C13 et C18 arrêt Mairie du 1er ou lignes 19, C14 et C3 à l’arrêt Terreaux
  • en vélo’v : stations Place Sathonay, Carmélites Burdeau, Place de la paix

[cubicweb] Logilab's roadmap for CubicWeb on May 15th, 2014

Publié le 2014-05-22 15:24:00

The Logilab team holds a roadmap meeting every two months to plan its CubicWeb development effort. Here is the report about the May 15th, 2014 meeting. The previous report posted to the blog was the march 2014 roadmap.

Versions

Version 3.17

This version is stable but old and maintainance will continue only as long as some customers will be willing to pay for it (current is 3.17.15).

Version 3.18

This version is stable and maintained (current is 3.18.4).

Version 3.19

This version was published at the end of April. It includes support for Cross Origin Resource Sharing (CORS) and a heavy refactoring that modifies sessions and sources to lay the path for CubicWeb 4.

For details read the release notes or the list of tickets for CubicWeb 3.19.0.

Version 3.20

This version is under development. It will try to reduce as much as possible the stock of patches in the state "reviewed", "awaiting review" and "in progress". If you have had something in the works that has not been accepted yet, please ready it for 3.20 and get it merged.

It should also include the work done for CWEP-002 (computed attributes and relations) and the merging of Connection and ClientConnection if it happens to be simple enough to get done quickly (in case the removal of dbapi would really help, this merging will wait for 3.21).

For details read list of tickets for CubicWeb 3.20.0.

Version 3.21 (or maybe 4.0?)

Removal of the dbapi and merging of CWEP-003 (adding a FROM clause to RQL).

Cubes

Here is a list of cubes that had versions published over the past two months: accidents, awstats, book, bootstrap, brainomics, cmt, collaboration, condor, container, dataio, expense, faq, file, forge, forum, genomics, geocoding, inlineedit, inventory, keyword, link, mailinglist, mediaplayer, medicalexp, nazcaui, ner, neuroimaging, newsaggregator, processing, questionnaire, rqlcontroller, semnews, signedrequest, squareui, task, testcard, timesheet, tracker, treeview, vcsfile, workorder.

Here are a the new cubes we are pleased to announce:

rqlcontroller receives via a POST a list of RQL queries and executes them. This is a way to build web services.

wsme is helping build a web service API on top of a CubicWeb database.

signedrequest is a simple token based authentication system. This is a way for scripts or callback urls to access an instance without login/pwd information.

relationwidget is a widget usable in forms to edit relationships between objects. It depends on CubicWeb 3.19.

searchui is an experiment on adding blocks to the list of facets that allow building complex RQL queries step by step by clicking with the mouse instead of directly writing the RQL with the keyboard.

ckan is using the REST API of a CKAN data portal to mirror its content.

CWEPs

Here is the status of open CubicWeb Evolution Proposals:

CWEP-0002 is now in good shape and the goal is to have it merged into 3.20. It lacks some documentation and a migration script.

CWEP-0003 has made good progress during the latest sprint, but will need a thorough review before being merged. It will probably not be ready for 3.20 and have to wait for 3.21.

New CWEPs are expected to be written for clarifying the API of the _cw object, supporting persistent sessions and improving the performance of massive imports.

Visual identity

CubicWeb has a new logo that will appear before the end of may on its revamped homepage at http://www.cubicweb.org

Last but not least

As already said on the mailing list, other developers and contributors are more than welcome to share their own goals in order to define a roadmap that best fits everyone's needs.

Logilab's next roadmap meeting will be held at the beginning of july 2014.

[logilab] SaltStack Meetup with Thomas Hatch in Paris France

Publié le 2014-05-22 11:25:00

This monday (19th of may 2014), Thomas Hatch was in Paris for dotScale 2014. After presenting SaltStack there (videos will be published at some point), he spent the evening with members of the French SaltStack community during a meetup set up by Logilab at IRILL.

http://www.logilab.org/file/248338/raw/thomas-hatch.png

Here is a list of what we talked about :

  • Since Salt seems to have pushed ZMQ to its limits, SaltStack has been working on RAET (Reliable Asynchronous Event Transport Protocol ), a transport layer based on UDP and elliptic curve cryptography (Dan Berstein's CURVE-255-19) that works more like a stack than a socket and has reliability built in. RAET will be released as an optionnal beta feature in the next Salt release.
  • Folks from Dailymotion bumped into a bug that seems related to high latency networks and the auth_timeout. Updating to the very latest release should fix the issue.
  • Thomas told us about how a dedicated team at SaltStack handles pull requests and another team works on triaging github issues to input them into their internal SCRUM process. There are a lot of duplicate issues and old inactive issues that need attention and clutter the issue tracker. Help will be welcome.
http://www.logilab.org/file/248336/raw/Salt-Logo.png
  • Continuous integration is based on Jenkins and spins up VMs to test pull request. There is work in progress to test multiple clouds, various latencies and loads.
  • For the Docker integration, salt now keeps track of forwarded ports and relevant information about the containers.
  • salt-virt bumped into problems with chroots and timeouts due to ZMQ.
  • Multi-master: the problem lies with syncronisation of data which is sent to minions but also the data that is sent to the masters. Possible solutions to be explored are : the use of gitfs, there is no built-in solution for keys (salt-key has to be run on all masters), mine.send should send the data at both masters, for the jobs cache: one could use an external returner.
  • Thomas talked briefly about ioflo which should bring queuing, data hierarchy and data pub-sub to Salt.
http://www.logilab.org/file/248335/raw/ioflo.png
  • About the rolling release question: versions in Salt are definitely not git snapshots, things get backported into previous versions. No clear definition yet of length of LTS versions.
  • salt-cloud and libcloud : in the next release, libcloud will not be a hard dependency. Some clouds didn't work in libcloud (for example AWS), so these providers got implemented directly in salt-cloud or by using third-party libraries (eg. python-boto).
  • Documentation: a sprint is planned next week. Reference documentation will not be completly revamped, but tutorial content will be added.

Boris Feld showed a demo of vagrant images orchestrated by salt and a web UI to monitor a salt install.

http://www.vagrantup.com/images/logo_vagrant-81478652.png

Thanks again to Thomas Hatch for coming and meeting up with (part of) the community here in France.

[tarek] French Services Hackaton #1

Publié le 2014-05-22 08:35:00

The Mozilla Cloud Services team just got a little bit reorganized and I am now managing a new subteam.

I am very happy about the new subteam I am part of: Alexis, Rémy and myself are the French Cloud Services team. We're still working on projects with other teams of course - but being a team in the same timezone and speaking the same native language helps a lot.

One topic that is owned by our team is building and maintaining tools that help build, deploy & run web services.

Currently, the three most active projects are:

  • Loads -- a distributed load testing tool we use to verify that a given service scales.
  • Circus -- an extensible process supervisor we're using in all our deployments
  • Cornice -- a Python framework on the top of Pyramid that helps you write web services - as opposed to "web pages"

Hackaton #1

Rémy & Alexis are in Rennes, and I am located not far from Dijon - so we're very close to each other. Closer than from our colleagues from the US or Canada. When the team was set, we've decided that we would gather for a couple of days once every month at the Mozilla Paris office to work on tools.

That's what we did this week. And that event is open to the community - we had the pleasure to have Boris coming and working with us during those 2 days.

We worked on the following topics:

  • We released the long overdue Circus 0.11
  • We made the Circus web dashboard compatible with several Circus instances. In other words, you can now supervise processes that are running on several servers from the same dashboard
  • We looked at some improvements in how Cornice publishes its APIs specifications.

But the most important task: we socialized, had fun around food/drinks.

The next hackaton will be sometimes in June. I'll try to announce it so more people can join us.

[logilab] Compte rendu présentation Salt à Solution Linux

Publié le 2014-05-21 18:57:00

Logilab était à l'édition 2014 de Solutions Linux qui se déroulait au CNIT à Paris. David Douard participait à la table ronde sur les outils libres pour la supervision lors de la session Administration Système, Devops, au cours de laquelle un certain nombre de projets libres ont été mentionnés : nagios, shinken, graphite, ElasticSearch, logstash, munin, saltstack, kibana, centreon, rsyslog.

http://www.logilab.org/file/248048/raw/solutionlinux.png

Suite à des présentations sur OpenLDAP, LXC, btrfs et ElasticSearch David Douard a présenté notre approche agile de l'administration système articulée autour de Salt et en particulier le principe de l'administration système pilotée par les tests (diapos) (Test-Driven Infrastructure).

https://www.logilab.org/file/248098/raw/Screenshot%20from%202014-05-21%2017%3A55%3A35.png

Merci aux organisateurs de Solutions Linux pour cette édition 2014.

[logilab] Salt April Meetup in Paris (France)

Publié le 2014-05-14 12:28:00

On the 15th of april, in Paris (France), we took part in yet another Salt meetup. The community is now meeting up once every two months.

We had two presentations:

  • Arthur Lutz made an introduction to returners and the scheduler using the SalMon monitoring system as an example. Salt is not only about configuration management Indeed!
  • The folks from Is Cool Entertainment did a presentation about how they are using salt-cloud to deploy and orchestrate clusters of EC2 machines (islands in their jargon) to reproduce parts of their production environment for testing and developement.

More discussions about various salty subjects followed and were pursued in an Italian restaurant (photos here).

In case it is not already in your diary : Thomas Hatch is coming to Paris next week, on Monday the 19th of May, and will be speaking at dotscale during the day and at a Salt meetup in the evening. The Salt Meetup will take place at IRILL (like the previous meetups, thanks again to them) and should start at 19h. The meetup is free and open to the public, but registering on this framadate would be appreciated.