Aller au contenu principal

Naviguer entre répertoires avec popd, pushd et cd

Parfois, il est nécessaire de naviguer entre plusieurs répertoires dont le chemin est long. Certes, les interpréteurs complètent les chemins, ce qui rend les manipulations moins douloureuses. Certes, cd - rend bien service lorsque l’on souhaite simplement revenir dans le répertoire précédent. Cependant, des shells comme Bash ou zsh possèdent une pile dans laquelle il est possible d’enregistrer des chemins pour les réutiliser par la suite. Utiliser cette pile est parfois une solution bien plus pratique.

Les commandes popd et push ne sont pas disponibles dans tous les interprètes de commandes. Par exemple, sh ne les a pas.

Quatres commandes sont nécessaires :

  • popd, pour empiler les répertoires ;
  • pushd, pour dépiler les répertoires ;
  • dirs, pour voir la pile ;
  • cd, pour se déplacer entre les répertoires. Oui, la commande que tout le monde connaît. :-)

Première visite

Empiler un répertoire

Partons d’une pile vide :

chaperonrouge@conte:/$ cd /maison
chaperonrouge@conte:/maison$ dirs -v
0 /maison

dirs affiche uniquement le répertoire actuel (donc /maison, à l’index 0), et rien d’autre car la pile ne possède qu’un seul élément. L’option -v permet d’afficher l’index.

déplacement dans un répertoire

Par défaut, pushd prend un répertoire en paramètre. Il empile ce répertoire, qui est donc à l’index 0. L’ancien répertoire à l’index 0 est décalé à l’index 1. Le nouveau répertoire de travail est donc celui qui est en 0. Enfin, pushd affiche l’état de la nouvelle pile.

Par exemple, en utilisant deux fois la commande pushd sur des répertoires différents :

chaperonrouge@conte:/maison$ pushd /chez/mere/grand
/chez/mere/grand /maison
chaperonrouge@conte:/chez/mere/grand$ dirs -v
0 /chez/mere/grand
1 /maison
chaperonrouge@conte:/chez/mere/grand$ pushd /dans/la/foret
/dans/la/foret /chez/mere/grand /maison
chaperonrouge@conte:/dans/la/foret$ dirs -v
0 /dans/la/foret
1 /chez/mere/grand
2 /maison

Pushd, comportement par défaut

Changer de répertoire

Pour se déplacer vers un répertoire enregistré dans la pile, il suffit de préfixer l’index par le caractère tilde (~). La pile reste inchangée.

Par exemple, chaperonrouge veut aller dans le répertoire /chez/mere/grand qui est actuellement à l’index 1 de la pile :

chaperonrouge@conte:/maison$ dirs -v
0 /dans/la/foret
1 /chez/mere/grand
2 /maison
chaperonrouge@conte:/$ cd ~1
chaperonrouge@conte:/chez/mere/grand$

Déplacement dans un répertoire enregistré dans la pile

Supprimer un répertoire

popd supprime un répertoire de la pile puis affiche le nouvel état de la pile.
Par défaut, popd supprime le premier répertoire de la pile et se déplace vers le répertoire qui est passé à l’index 0.

Par exemple, chaperonrouge décide de faire le ménage :

chaperonrouge@conte:/maison$ dirs -v
0 /maison
1 /en/chemin
2 /dans/la/foret
3 /chez/mere/grand
chaperonrouge@conte:/maison$ popd
/en/chemin /dans/la/foret /chez/mere/grand
chaperonrouge@conte:/en/chemin$ dirs -v
0 /en/chemin
1 /dans/la/foret
2 /chez/mere/grand

Popd, comportement par défaut

Il est aussi possible de supprimer un élément quelconque de la pile en précisant l’index de l’élément à supprimer. Dans ce cas, popd ne change pas le répertoire actuellement utilisé (le chemin enregistré à l’index 0 n’a pas changé).

chaperonrouge@conte:/maison$ dirs -v
0 /maison
1 /dans/la/foret
2 /chez/mere/grand
3 /dans/le/ventre/du/loup
chaperonrouge@conte:/maison$ popd +2
/maison /dans/la/foret /dans/le/ventre/du/loup
chaperonrouge@conte:/maison$

Popd (sélection d'un répertoire particulier)

Autres possiblités

L’option -n de pushd permet d’empiler le répertoire passé en paramètre sans se déplacer :

chaperonrouge@conte:/maison$ dirs -v
0 /maison
1 /dans/la/foret
2 /chez/mere/grand
chaperonrouge@conte:/maison$ pushd -n /porte/du/village
0 /maison
1 /porte/du/village
1 /dans/la/foret
2 /chez/mere/grand
/maison /porte/du/village /dans/la/foret /chez/mere/grand
chaperonrouge@conte:/maison$

Pushd, sans déplacement

Mettre le répertoire de travail dans la pile :

chaperonrouge@conte:/maison$ dirs -v
0 /maison
1 /dans/la/foret
2 /chez/mere/grand
chaperonrouge@conte:/maison$ pushd .
/maison /maison /dans/la/foret /chez/mere/grand
chaperonrouge@conte:/maison$

Pushd, empilement du répertoire actuel

L’option -c de dirs vide la pile des répertoires enregistrés :

chaperonrouge@conte:/maison$ dirs -v
0 /maison
1 /dans/la/foret
2 /chez/mere/grand
chaperonrouge@conte:/maison$ dirs -c
chaperonrouge@conte:/maison$ dirs -v
0 /maison

Vider la pile

Il est possible de compter l’index de la pile en partant de la fin (-0 pour le dernier, -1 pour l’avant dernier, etc.). Le comportement est équivalent aux index de liste en Python (et probablement dans beaucoup d’autres langages).

Voici un exemple pour aller dans le dernier répertoire de la pile :

chaperonrouge@conte:/maison$ dirs -v
0 /maison
1 /dans/la/foret
2 /chez/mere/grand
chaperonrouge@conte:/maison$ cd ~-0
chaperonrouge@conte:/chez/mere/grand$

Déplacement dans un répertoire de la pile, comptage par la fin

Les options de ces commandes sont évidemment non exhaustives.

Logiciels utilisés et codes source des schémas

Pour avoir la documentation des commandes, il faut utiliser « man bash » et non « man pushd ».

Le comportement des outils est basé sur Bash, version 4.2.45(1)-release.

Les schémas ont été réalisés avec ditaa, version 0.9. La version utilisée provient du paquet Debian du même nom.
La commande de base à utiliser est :

$ ditaa pushdpopd_exemple1.txt pushdpopd_exemple1.png

Voici le code source des schémas inclus dans l’article :
pushdpopd_exemple1 :

/-------------------\       +-------------+          /-------------------\
| 0 /               |-------: cd /maison  |--------->| 0 /maison         |
\-------------------/       +-------------+          \-------------------/
/-------------------\                                /-------------------\
| cYEL(vide)        |                                | cYEL(vide)        |
\-------------------/                                \-------------------/

pushdpopd_exemple2 :

/-------------------------\      +---------------------------+       /-------------------------\
| 0 /maison               |------: pushd /chez/mere/grand    |------>| 0 /chez/mere/grand      |--+
\-------------------------/      +---------------------------+       \-------------------------/  |
/-------------------------\                                          /-------------------------\  |
| cYEL(vide)              |                                          | cYEL1 /maison           |  |
\-------------------------/                                          \-------------------------/  |
                                                                                                  |
/-------------------------\      +---------------------------+                                    |
| 0 /dans/la/foret        |<-----: pushd /dans/la/foret      |------------------------------------+
\-------------------------/      +---------------------------+
/-------------------------\
| cYEL1 /chez/mere/grand  |
+-------------------------+
| cYEL2 /maison           |
\-------------------------/

pushdpopd_exemple3 :

/-------------------------\       +-------------------------+            /-------------------------\
| 0 /dans/la/foret        |-------: cd ~1                   |----------->| 0 /chez/mere/grand      |
\-------------------------/       +-------------------------+            \-------------------------/
/-------------------------\                                              /-------------------------\
| cYEL1 /chez/mere/grand  |                                              | cYEL1 /chez/mere/grand  |
+-------------------------+                                              +-------------------------+
| cYEL2 /maison           |                                              | cYEL2 /maison           |
\-------------------------/                                              \-------------------------/

pushdpopd_exemple4 :

/-------------------------\       +-------------------------+            /-------------------------\
| 0 /maison               |-------: popd                    |----------->| 0 /en/chemin            |
\-------------------------/       +-------------------------+            \-------------------------/
/-------------------------\                                              /-------------------------\
| cYEL1 /en/chemin        |                                              | cYEL1 /dans/la/foret    |
+-------------------------+                                              +-------------------------+
| cYEL2 /dans/la/foret    |                                              | cYEL2 /chez/mere/grand  |
+-------------------------+                                              \-------------------------/
| cYEL3 /chez/mere/grand  |
\-------------------------/

pushdpopd_exemple5 :

/-------------------------------\       +-----------------------+        /-------------------------------\
| 0 /maison                     |-------: popd  +2              |------->| 0 /maison                     |
\-------------------------------/       +-----------------------+        \-------------------------------/
/-------------------------------\                                        /-------------------------------\
| cYEL1 /dans/la/foret          |                                        | cYEL1 /dans/la/foret          |
+-------------------------------+                                        +-------------------------------+
| cYEL2 /chez/mere/grand        |                                        | cYEL2 /dans/le/ventre/du/loup |
+-------------------------------+                                        \-------------------------------/
| cYEL3 /dans/le/ventre/du/loup |
\-------------------------------/

pushdpopd_exemple6 :

/-------------------------\       +----------------------------+         /-------------------------------\
| 0 /maison               |-------: pushd -n /porte/du/village |-------->| 0 /maison                     |
\-------------------------/       +----------------------------+         \-------------------------------/
/-------------------------\                                              /-------------------------------\
| cYEL1  /dans/la/foret   |                                              | cYEL1 /porte/du/village       |
+-------------------------+                                              +-------------------------------+
| cYEL2 /chez/mere/grand  |                                              | cYEL2 /dans/la/foret          |
\-------------------------/                                              +-------------------------------+
                                                                         | cYEL3 /chez/mere/grand        |
                                                                         \-------------------------------/

pushdpopd_exemple7 :

/-------------------------\       +----------------------------+         /-------------------------------\
| 0 /maison               |-------: pushd .                    |-------->| 0 /maison                     |
\-------------------------/       +----------------------------+         \-------------------------------/
/-------------------------\                                              /-------------------------------\
| cYEL1  /dans/la/foret   |                                              | cYEL1 /maison                 |
+-------------------------+                                              +-------------------------------+
| cYEL2 /chez/mere/grand  |                                              | cYEL2 /dans/la/foret          |
\-------------------------/                                              +-------------------------------+
                                                                         | cYEL3 /chez/mere/grand        |
                                                                         \-------------------------------/

pushdpopd_exemple8 :

/-------------------------\       +----------------------------+         /-------------------------------\
| 0 /maison               |-------: dirs -c                    |-------->| 0 /maison                     |
\-------------------------/       +----------------------------+         \-------------------------------/
/-------------------------\                                              /-------------------------------\
| cYEL1  /dans/la/foret   |                                              | cYEL (vide)                   |
+-------------------------+                                              \-------------------------------/
| cYEL2 /chez/mere/grand  |
\-------------------------/

pushdpopd_exemple9 :

/---------------------------\       +----------------------------+         /-------------------------------\
| 0 /maison              -2 |-------: cd ~-0                     |-------->| 0 /chez/mere/grand            |
\---------------------------/       +----------------------------+         \-------------------------------/
/---------------------------\                                              /-------------------------------\
| cYEL1  /dans/la/foret  -1 |                                              | cYEL1 /dans/la/foret          |
+---------------------------+                                              +-------------------------------+
| cYEL2 /chez/mere/grand -0 |                                              | cYEL2 /chez/mere/grand        |
\---------------------------/                                              \-------------------------------/

Attaquer n’importe quel serveur comme dans les films

Lorsqu’un film représente une personne attaquant un système informatique, on nous montre parfois quelqu’un tapant frénétiquement sur un clavier des commandes plus ou moins crédibles.

Si seulement il existait une commande shell pour faire n’importe quelle attaque, donc adaptée à n’importe quel scénario…
Par exemple :
$ attack --rf extraterrestres #Independance day
$ attack le_grand_mechant_caricatural #la liste ne rentrera jamais sur 80 colonnes

Malheureusement, on obtient un résultat de ce genre :
$ attack nsa
bash: attack : commande introuvable

Sur Ubuntu, un message d’erreur signalera que la commande est disponible une fois le paquet adéquat installé. Sur Debian, il faut installer le paquet command-not-found et mettre à jour pour avoir les suggestions. Sur une autre distribution, j’imagine que c’est aussi disponible mais j’ignore la procédure.
# aptitude install command-not-found
# update-command-not-found

Et là pouf, on progresse :
$ attack nsa
The program 'attack' is currently not installed. To run 'attack' please ask your administrator to install the package 'ladr4-apps'
attack: command not found

Le paquet ladr4-apps semble donc la solution magique, sauf qu’elle ne l’est pas. C’est un ensemble d’outils et de bibliothèques pour construire des preuves.

LADR (Library for Automated Deduction Research) is a library for
use in constructing theorem provers. Among other useful routines it
provides facilities for applying inference rules such as resolution
and paramodulation to clauses. LADR is used by the prover9 theorem
prover, and by the mace4 countermodel generator.

…Encore raté ! Il faudra encore continuer à copier/coller du code pour illustrer les aventures du héros. ;-)

Évolution comparée du nombre de bogues entre distribution Linux

Il est difficile de connaitre la vitalité d’une distribution Linux. Il est possible de s’en faire une idée en fonction du nombre de posts sur des forums, de recherche sur un moteur de recherche, du nombre de téléchargement ou la visibilité sur Distrowatch, etc. Regarder le nombre de bogues en est une autre. Après tout, on ne signale des bogues que sur les distributions (et les logiciels) que l’on utilise… C’est celle qu’utilise bubulle.

Le but de l’article est de visualiser l’évolution du nombre de bogues entre Arch Linux, Debian, Ubuntu et RedHat. Puis de poser des pistes sur les causes possibles. À la fin de l’article, des liens vers les scripts de récupération des données (en python, à l’aide des bibliothèques requests et beautifulSoup) et les représentations graphiques (en python, avec la bibliothèque matplotlib) sont fournis.

Résultats obtenus

En bogues cumulés

Bogues cumulés

ArchLinux a un score extrêmement faible (moins de 40.000 bogues) comparé aux autres distributions.
Je connais mal ArchLinux donc je resterai au stade des hypothèses :

  • Je n’ai pas regardé le bon bug tracker. J’ai utilisé les données fournies sur bugs.archlinux.org.
  • Arch aurait un mode de travail différent des 3 autres distributions (par exemple si les problèmes sont signalés directement au responsable du paquet).
  • Arch n’aurait quasiment pas de bogue. Mon expérience personnelle de cette distribution me fait exclure cette hypothèse.
  • Arch aurait finalement peu d’utilisateurs.

Lors de la deuxième moitié 2007, Redhat a une augmentation durable dont j’ignore l’origine. La sortie de RHEL 5 ne me semble pas être une explication très convaincante.

Ubuntu, dernière distribution créée, dépasse toute les autres en 2010. La croissance reste rapide au fil du temps.

Sur le long terme, la croissance de Debian est globalement la même. La croissance des rapports de bogues est plus faible pour Debian qu’Ubuntu. Quelques hypothèses, non exclusives entre elles :

  • Moins d’utilisateurs pour Debian qu’Ubuntu. Ubuntu ayant été créée après, elle aurait dépassée Debian au début 2007 (en supposant un nombre de rapports envoyés par utilisateur égal entre les deux distributions).
  • L’interface web d’Ubuntu faciliterait plus le signalement de bogues que l’utilisation d’e-mails pour communiquer avec le BTS utilisé par Debian
  • On m’a signalé que reportbug, l’outil de signalement de bogues de Debian, aurait lui-même eu des problèmes pendant un moment. Cependant je ne pense pas que ce soit une cause significative sur une période longue.
  • Il y aurait plus d’envois automatiques lors de plantage chez Ubuntu que chez Debian (par exemple lorsque les paquets n’arrivent pas à être reconstruit – FTBFS).

Variations de la croissance du nombre de bogues

Variations au fil du temps

On constate un ralentissement de l’augmentation ces dernières dernières années pour Ubuntu (depuis 2010) et Debian (depuis 2006-2007) et une accélération pour RedHat, au point de rattraper celle de la phase base d’Ubuntu. En effet, la croissance pour Ubuntu subit des cycles en fonctions des publications tous les 6 mois.

C’est le même phénomène que celui de Debian lors de la préparation d’une nouvelle version stable. Phénomène peu visible sur le graphique ci-dessus, il faut regarder un graphique limité aux bogues de Debian.
Concernant Debian, la mesure de l’usage faite avec PopCon montre une augmentation ; il serait intéressant de voir si l’usage ralentit parallèlement à celle des rapports de bogues.

Si la mesure en nombre de bogues est pertinente, la distribution qui monte est RedHat plutôt qu’Ubuntu ou Arch.

Limites de l’approche

L’estimation du nombre de bogues est basé sur les identifiant des bogues donc les résultats peuvent être approximatifs.

Quelques données semblaient aberrantes, elles ont été supprimées des résultats. Les voici :

distrb id_bug AAAA MM JJ
redhat 100213 2002 05 06
redhat 780001 2010 09 29
redhat 900001 2012 03 08
ubuntu 80001 2005 07 25

La comparaison des valeurs absolues entre distribution n’a pas forcément de sens car on ne mesure pas les mêmes choses. C’est d’autant plus vrai que les distributions sont éloignées. Les variations et l’évolution de la variation semble plus pertinente même si elles sont à prendre avec précaution vu les erreurs de mesure…

Méthode de récolte des données et traitement

La récolte des données a été faite avec un script python qui télécharge des pages sur les interfaces web des rapports de bogues (merci requests !) puis cherche la date de création de l’alerte (merci BeautifulSoup !).

Le script est téléchargeable : dl_stats.py.
La bibliothèque requests permet de simplifier la récupération du code html. Lorsqu’il y a une redirection, la bibiothèque suit le lien automatiquement pour obtenir le contenu. Par exemple, pour Ubuntu, l’adresse https://bugs.launchpad.net/bugs/308191 redirige automatiquement vers https://bugs.launchpad.net/ubuntu/+source/xf86-input-multitouch/+bug/308191. Il suffit donc de faire :

r = requests.get("https://bugs.launchpad.net/bugs/308191")

Les statistiques sont écrites sur la sortie standard et doivent être copiées dans des fichiers .txt, un par distribution. Les fichiers seront lus par le script de traçage des graphiques. Ce script utilise matplotlib et est disponible à http://stephane.yaal.fr/evolution-rapports-de-bogues/draw_stats.py. Les fichiers de statistiques utilisés sont disponibles dans le même répertoire (http://stephane.yaal.fr/evolution-rapports-de-bogues/).

Inspirations

La création des graphique est basée sur l’exemple de l’évolution du prix de l’essence disponible sur geophysique.be (évolution du prix de l’essence).

La documentation de matplolib pour personnaliser ces graphiques : pyplot.plot

Merci à Christian Perrier (bubulle) pour cette façon originale d’estimer la vitalité d’une distribution.

Merci aussi à Nirgal, Joey Hess et tout ceux avec qui j’en ai parlé à la DebConf 13 pour leurs réflexions.

Histogramme cumulé de la répartition des cartes du jeu The City avec matplotlib

The city est un jeu de cartes où chaque joueur pose des bâtiments, représentés par des cartes. Elles ont chacune un coût (compris entre 0 à 11), génère un revenu et des points de victoires. La plupart d’entre elles existent en plusieurs exemplaires. Certaines cartes possèdent aussi des symboles (fontaine, caddie et voiture) qui influencent le revenu ou les points gagnés.

Une carte du jeu

La répartition de ces symboles n’est pas uniforme comme on peut le constater sur l’histogramme suivant :
Répartition des cartes

Le graphique a été réalisé avec matplotlib, une bibilothèque python pour créer des graphiques 2D ou 3D. La façon de le réaliser sera abordée dans une seconde partie, la première étant consacrée à quelques remarques mise en évidence par le graphique.

Interprétation et limitation

Quelques faits mis en lumière par l’histogramme :

  • Plus les cartes coûtent cher, plus elles sont rares. Les cartes les plus courantes sont souvent en plusieurs exemplaires alors que les dernières sont uniques. Cependant certaines des moins onéreuses ne peuvent être joués qu’en un seul exemplaire.
  • Une stratégie Fontaine-Voiture semble plus difficile que Fontaine-Caddie ou Caddie-Voiture car le nombre de cartes ayant les deux couleurs ensemble est bien plus faible.
  • La carte Caddie la plus forte vaut 7, alors que pour les deux autres couleurs c’est 11. Plus coûteux, mais plus puissant…

Le graphique a aussi des limites :

  • La stratégie sans couleur ne semble pas pertinente alors que les Villas (sans couleur) valent 4 et ont une très bonne synergie entre elles.
  • Le graphique compte le nombre de cartes, mais certaines cartes de la moitié supérieure peuvent avoir plusieurs fois le même symboles (maximum trois). Le graphique donne donc une idée de la probabilité d’obtenir une carte avec le symbole donné, pas la probabilité du nombre de symboles obtenus.

Réalisation

L’interface de programmation ressemble à Pychart, une autre bibliothèque python pour faire des graphiques, présentée dans un article précédent. (Entre les deux, préférez matplotlib. (Oui, j’aime bien les parenthèses. (Pas vous ?)))

Par défaut, la sortie du graphique est dans une fenêtre de l’environnement de bureau. C’est pratique lorsqu’on fait des tests avec l’interpréteur python. C’est prévu pour, il existe même une option pour avoir directement matplotlib chargé au démarrage avec ipython (ipython --pylab).
Il est possible de changer la sortie au démarrage du script, à condition de le faire avant d’importer pyplot.
Pour avoir une sortie en PNG :

import matplotlib
matplotlib.use('Agg') # au début du script
from matplotlib import pyplot as plt

# ...
# plein de code malin et très lisible
# ...

plt.savefig("/tmp/thecity-histogramme.png")

Les données sont fournies dans un n-uplet représentant la distribution d’une valeur sur l’ensemble des barres. Par exemple, pour représenter la combinaison Fontaine-Voiture-Caddie (notée BVO) :

BVO = (3, 0, 2, 0, 1, 0, 0, 0, 0, 0, 0, 0) # répartition de la caractéristique BVO
p1 = plt.bar(index, BVO, WIDTH, color="#D70751") # représentation dans le graphique

C’est comme si on empilait les couches de données les unes au-dessus des autres. Pour les deuxièmes caractéristiques suivantes, il faut ajouter un paramètre bottom qui fournit la hauteur de départ pour la nouvelle couche.

p2 = plt.bar(index,
             BO,
             WIDTH,
             color="#D217F4",
             bottom=BVO)

Comme la hauteur sera différente pour chaque valeur, j’ai ajoutée une fonction qui fait la somme des listes pour la troisième couche et supérieures. C’est du code Python générique, donc utilisable dans n’importe quel autre contexte :

import itertools
def sum_cards(cards):
    sum_cards_by_value = lambda x, y: map(sum, itertools.izip(x, y))
    return reduce(sum_cards_by_value, cards)

Comportement :

In [4]: sum_cards([[1, 2, 3], [10, 20, 30]])
Out[4]: [11, 22, 33]

In [5]: sum_cards([[1, 2, 3], [10, 20, 30], [100, 200, 300]])
Out[5]: [111, 222, 333]

Le reste du code reste compréhensible simplement en le lisant ; il est fourni en fin de l’article.

À partir de matplotlib 1.2.0, un graphique pour des données continues est aussi disponible. Il est nommé stackplot (voir l’exemple fourni par matplotlib).

Sources

La boîte de jeu, amenée par Arthur, avec laquelle on joue dans la boîte.

Prise en main de matplotlib

Un exemple d’histogramme fourni par matplotlib

Script de génération de l’histogramme :

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

import itertools
import matplotlib
matplotlib.use('Agg')

import numpy as np

from matplotlib import pyplot as plt


BVO = (3, 0, 2, 0, 1, 0, 0, 0, 0, 0, 0, 0)
BO  = (0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0)
BV  = (0, 4, 2, 5, 0, 0, 0, 1, 0, 0, 0, 0)
VO  = (0, 7, 5, 0, 2, 0, 1, 0, 1, 1, 0, 0)
B   = (0, 7, 0, 4, 1, 3, 2, 1, 3, 1, 0, 1)
V   = (0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0)
O   = (0, 0, 2, 3, 3, 0, 1, 0, 1, 0, 0, 1)
no  = (0, 13, 11, 0, 8, 0, 0, 0, 0, 0, 0, 1)

WIDTH = 0.55

def max_sum():
    return max([
        BVO[i] + BO[i] + BV[i] + VO[i] + B[i] + V[i] + O[i] + no[i]
        for i
        in range(data_length())])

def data_length():
    return len(BVO)

def higher_card_cost():
    return data_length() - 1


index = np.arange(data_length())

def sum_cards(cards):
    sum_cards_by_value = lambda x, y: map(sum, itertools.izip(x, y))
    return reduce(sum_cards_by_value, cards)


p1 = plt.bar(index, BVO, WIDTH, color="#D70751")
p2 = plt.bar(index, BO, WIDTH, color="#D217F4", bottom=BVO)
p3 = plt.bar(index, BV, WIDTH, color="#0ED5D3", bottom=sum_cards([BVO, BO]))
p4 = plt.bar(index, VO, WIDTH, color="#E7F417", bottom=sum_cards([BVO, BO, BV]))
p5 = plt.bar(index, B, WIDTH, color="#0101f3", bottom=sum_cards([BVO, BO, BV, VO]))
p6 = plt.bar(index, V, WIDTH, color="#2fc62b", bottom=sum_cards([BVO, BO, BV, VO, B]))
p7 = plt.bar(index, O, WIDTH, color="#F3B439", bottom=sum_cards([BVO, BO, BV, VO, B,  V]))
p8 = plt.bar(index, no, WIDTH, color="#999999", bottom=sum_cards([BVO, BO, BV, VO, B, V, O]))


plt.ylabel(u"Quantité")
plt.xlabel(u"Coût")
plt.title("Distribution des cartes de The City")
plt.xticks(index+WIDTH/2., [str(i) for i in range(data_length())])
plt.yticks(np.arange(0, (max_sum() + 1), 10))
plt.legend((p1[0], p2[0], p3[0], p4[0], p5[0], p6[0], p7[0], p8[0]),
           ('Fontaine, Caddie, Voiture (BVO)', 'Fontaine, Voiture (BO)',"Fontaine, Caddie (BV)", "Caddie, Voiture (VO)", "Fontaine (B)", "Caddie (V)", "Voiture (O)", "Aucune couleur"))

plt.savefig("/tmp/thecity-histogramme.png")

DebConf sur la planète

Le terme DebConf est une abréviation pour Debian Conference. Ce sont des conférences annuelles qui se déroulent à chaque fois dans une ville différente. La DebConf13, conférence ayant le numéro 13 mais qui est la quatorzième parce qu’il y a eu une conférence numéro 0, commence bientôt (le matin du dimanche 11 août 2013) et je vais leur infliger ma présence ! :)
Je vais à la DebConf13

Les précédentes DebConf ont eu lieu en Europe, en Amérique du Nord, Centrale et Sud. L’Afrique et l’Asie n’ont jamais accueilli une de ces conférences mais le nombre de développeurs Debian y est bien plus faible.
Voici l’emplacement des différentes DebConf sur un planisphère :
Les DebConf sur la planète

En rouge, les DebConf passées.
En blanc celle qui est imminente et à Vaumarcus, en Suisse.
En jaune, celle qui sera faite l’année prochaine et à Portland, aux États-Unis.

Réalisation de la carte

La carte a été réalisée avec xplanet, installable avec le paquet éponyme. Éponyme signifiant « du même nom », faites « apt-get install xplanet », pas « apt-get install eponyme ».

commande utilisée

xplanet -output debconf_planet.png -geometry 1024x512 -projection Mercator -config debconf_planet.conf -num_times 1

…qui permet d’écrire une image nommée debconf_planet.png, de 1024 pixels sur 512. La projection de la carte est celle de Mercator. Par défaut, on n’a qu’une vue partielle de la Terre (celle que l’on verrait de l’espace). Des éléments de configuration sont dans un fichier nommé debconf_planet.conf et la commande ne sera exécutée qu’une seule fois. Par défaut, xplanet tourne en boucle et rafraichit l’image régulièrement. Cela permet, par exemple, de mettre à jour un économiseur d’écran basé sur xplanet.

debconf_planet.conf

[earth]
shade=100
marker_file=coords.txt
marker_fontsize=15

shade vaut 100, ce qui permet d’ignorer l’effet jour/nuit qui est appliqué par défaut. coords.txt contient les latitudes et longitudes des points à afficher sur la carte.

coords.txt

+44.80 +0.58 "0&1" #Bordeaux, France
+43.65 -79.38 "2" #Toronto, Canada
+59.92 +10.75 "3" #Oslo, Norway
-29.99 -51.22 "4" #Porto Alegre, Brazil
+60.22 +24.66 "5" #Espoo, Finland
+18.91 -98.97 "6" #Oaxtepec, Mexico 
+55.96 -3.19 "7" #Edinburgh, Scotland
-37.96 -57.59 "8" #Mar del Plata, Argentina
+39.60 -6.08 "9" #Extremadura, Spain
+40.74 -74.00 "10" #New York City, USA
+44.78 +17.21 "11" #Banja Luka, Republika Srpska, Bosnia and Herzegovina
+12.14 -86.25 "12" #Managua, Nicaragua
+46.87 +6.75 "13" color=white #Le Camp, Vaumarcus, Switzerland
+45.53 -122.67 "14" color=yellow #Portland, Oregon, USA

Références

Les dates et lieux des conférences passées et présente sont listées sur la page
https://wiki.debian.org/DebConf.
L’annonce de la conférence 2014 qui se tiendra à Portland a été faite par le responsable du projet Debian.

xplanet dispose de nombreuses autres options. En plus de la page de manuel, plusieurs README sont disponibles dans les répertoires contenus dans /usr/share/xplanet/.
Un exemple de ce qu’il est aussi possible de faire : http://en.wikipedia.org/wiki/Wikipedia:Producing_maps_with_xplanet