-
samedi 29 octobre 2011 à 17:37:25
Le Python, l'Introspection et le Singe #2
Ce billet est la suite directe du précédent sur le même sujet. Je vous invite donc plus que fortement à aller le lire (voire le relire).
Comme je le disais dans le précédent billet, les fonctions ne sont pas immuables. Mais attention, ne me faites pas dire ce que je n'ai pas dit : on ne peut pas modifier, à proprement parler, le code d'une fonction. Mais on peut le remplacer par un autre.
Après consultation de la documentation officielle du module inspect, on apprend qu'une fonction est caractérisée par 5 attributs :
- func_code : son code sous forme de bytecode dans un code object (parfaitement immuable)
- func_defaults : les valeurs par défaut de ses arguments
- func_doc : sa docstring
- func_globals : l'espace de noms global dans lequel elle a été définie
- func_name : son nom
On va donc pouvoir modifier notre fonction _replace pour qu'elle aille changer ces 5 attributs. Celà implique que l'on n'a plus besoin de faire un parcours récurssif depuis la base du module et que l'on peut se passer du module inspect.
Voici le code avant :
def _replace(module, from_, to, processed=None, ismodule=_inspect.ismodule): if processed is None: processed = list() if module in processed: return processed.append(module) for name in dir(module): attr = getattr(module, name) if ismodule(attr): _replace(attr, from_, to, processed) elif attr is from_: setattr(module, name, to)Et le voici après :
def _replace(from_, to): for name in ('doc', 'name', 'defaults', 'code', 'globals'): attr_name = 'func_' + name setattr(from_, attr_name, getattr(to, attr_name))Ce code a malheureusement un effet de bord tellement implicite qu'on l'oublierait presque. Rappelons nous ce que nous faisons. On va remplacer les 5 attributs qui font d'une fonction une fonction. Chaque référence vers cette fonction sera donc indirectement affectée par cette modification. Avec le code précédent, on ne faisait que modifier une référence pour qu'elle pointe vers une autre fonction. Là, la fonction reste la même (dans le sens où on ne change pas d'instance : seul son état est altéré). Donc en appliquant _replace sur _webpy.net.validip, _webpy.wsgi.validip sera aussi affectée puisqu'étant la même fonction (c'est justement ce qui nous évite de devoir refaire un parcours récursif).
Le problème est donc que l'on n'a plus accès à l'ancienne fonction ! Dans certains cas, ça peut ne pas être génant. Mais pour notre exemple, c'est bloquant. Il va donc falloir créer un genre de copie de sauvegarde de l'ancienne fonction. Pour cela on va créer une fonction vide et lui assigner les 5 attributs de l'ancienne fonction. On placera ensuite une référence de cette fonction dans la fonction qu'on remplace. Ceci n'est peut-être pas très clair, mais vous allez vite comprendre avec le code :
def _replace(from_, to): def old(): pass for name in ('doc', 'name', 'defaults', 'code', 'globals'): attr_name = 'func_' + name setattr(old, attr_name, getattr(from_, attr_name)) setattr(from_, attr_name, getattr(to, attr_name)) from_.old = oldOn regagne ainsi la possibilité d'appeler la fonction « remplacée » (entre guillemets, parce qu'au final ce n'est pas l'instance de la fonction que l'on a remplacé, mais certains de ses attributs) via l'attribut old. Veuillez noter au passage que rien ne m'obligeait à appeler la fonction vide avec le même nom que celui que j'utilise pour la stocker dans la fonction à « remplacer ».
Cette fonction ne prend par contre pas en charge les méthodes. En effet, une méthode n'est pas une fonction et n'a donc pas les 5 attributs cités plus haut. Par contre, une méthode possède une fonction accessible via l'attribut im_func. Il ne nous reste plus qu'à tester la présence d'un tel attribut :
if hasattr(from_, 'im_func'): from_ = from_.im_funcVoici ce que donne le code avec ces modifications :
import imp as _imp import sys as _sys _here = _sys.path.pop(0) _fp, _pathname, _description = _imp.find_module('web') _webpy = _imp.load_module('web', _fp, _pathname, _description) _sys.path.insert(0, _here) def _replace(from_, to): def old(): pass if hasattr(from_, 'im_func'): from_ = from_.im_func for name in ('doc', 'name', 'defaults', 'code', 'globals'): attr_name = 'func_' + name setattr(old, attr_name, getattr(from_, attr_name)) setattr(from_, attr_name, getattr(to, attr_name)) from_.old = old def _validip(ip, defaultaddr='127.0.0.1', defaultport=8080): return validip.old(ip, defaultaddr, defaultport) _replace(_webpy.net.validip, _validip) del _imp, _sys, _here, _fp, _pathname, _description, _webpy, _replace, _validipVous remarquerez la modification apportée à _validip. Nous n'avons en effet plus besoin d'une référence sur l'ancienne fonction, puisque l'on est dedans. Notre fonction _replace a pris le code de notre fonction _validip et l'a donné à _webpy.net.validip. Ainsi, lorsque l'on appelle _webpy.net.validip, c'est le code de notre _validip qui est exécuté mais dans le contexte de _webpy.net.validip. Ce qui implique que l'on va pouvoir accéder à son attribut old sans devoir le passer en argument de la fonction et que la fonction s'appelle validip et non _validip. On aurait pu appeler la fonction autrement que ça ne changerait rien :
def _quux(ip, defaultaddr='127.0.0.1', defaultport=8080): return validip.old(ip, defaultaddr, defaultport) _replace(_webpy.net.validip, _quux)Si vous avez bien suivi tout ce qu'on a fait jusqu'à présent, vous vous serez rendus compte d'une chose : dans notre cas précis, on peut faire beaucoup plus simple. On a vu que ce qui caractérisait une fonction, étaient les 5 attributs cités en début de billet. Celui qui nous intéresse ici est func_defaults. Comme dit plus haut, il contient les valeurs par défaut des arguments de la fonction. Ainsi, _webpy.net.valid.func_defaults vaut « ('0.0.0.0', 8080) ». Il nous suffit alors juste de changer cette valeur.
On pourrait donc se limiter à :
import imp as _imp import sys as _sys _here = _sys.path.pop(0) _fp, _pathname, _description = _imp.find_module('web') _webpy = _imp.load_module('web', _fp, _pathname, _description) _sys.path.insert(0, _here) _webpy.net.validip.func_defaults = ('127.0.0.1', 8080) del _imp, _sys, _here, _fp, _pathname, _description, _webpyMais ceci n'est valable que parce que justement on n'a pas besoin de faire autre chose que de changer une valeur par défaut. Parfois, suivant nos besoins, le code devra vraiment être « modifié » et alors on devra nécessairement avoir recours à la fonction _replace.
Repenchons nous un peu sur le chargement du module webpy. La fonction _imp.find_module() renvoie 3 choses :
- le fichier du module ouvert en lecture ou None si le module est un package
- le chemin absolu vers le module
- un tuple de 3 éléments décrivant un type de module (référez-vous à la documentation de imp.get_suffixes() pour en savoir plus)
webpy étant un package, _fp vaudra toujours None. Mais dans le cas où on utiliserait ce code sur un module n'étant pas un package, on devrait fermer le fichier. De même, si une erreur survient durant l'import du module, une exception de type ImportError est déclenchée. Étant donné que l'on est censé remplacer un module pré-existant, autant laisser l'utilisateur se débrouiller avec l'exception si le module d'origine n'est pas disponible. Par contre, on doit quand même dans tous les cas fermer le fichier.
En faisant un peu plus attention à la documentation de imp.find_module(), on voit que l'on peut passer sa propre liste de chemins plutôt que de se reposer sur sys.path. Ça sera plus propre de faire comme ça et ça fera plaisir à ThibG. Les 4 lignes d'import de webpy deviennent donc :
_fp, _pathname, _description = _imp.find_module('web', _sys.path[1:]) try: _webpy = _imp.load_module('web', _fp, _pathname, _description) except: if _fp: _fp.close()On commence enfin à avoir quelque chose qui tient la route. Il nous reste encore à voir pour faire les modifications qui nous permettront de ne plus être obligé de mettre notre web.py dans le même répertoire que notre projet. J'ai par exemple plusieurs projets utilisant webpy. J'aimerai bien ne pas devoir mettre le fichier dans chacun de ces projets, mais plutôt à un endroit accessible à tous. L'endroit le plus approrié me semble être ~/.local/lib/python2.7/site-packages/. Il ne nous reste alors plus qu'à retirer ce chemin, ainsi que tout ceux se trouvant avant dans sys.path (simple question de logique).
import os as _os _path = _sys.path[_sys.path.index(_os.path.dirname(__file__)) + 1:] _fp, _pathname, _description = _imp.find_module('web', _path)Bien que vous ayant donné un exemple de chemin où mettre notre fichier web.py, le code reste suffisamment générique pour fonctionner avec n'importe quel emplacement. Vous remarquerez aussi que je ne traite pas le cas particulier où _sys.path.index() ne trouverait pas le chemin. Notre fichier devant nécessairement être dans sys.path pour être importé, ce problème ne peut survenir.
Nous voici donc avec une version plus que satisfaisante :
import imp as _imp import os as _os import sys as _sys _path = _sys.path[_sys.path.index(_os.path.dirname(__file__)) + 1:] _fp, _pathname, _description = _imp.find_module('web', _path) try: _webpy = _imp.load_module('web', _fp, _pathname, _description) finally: if _fp: _fp.close() _webpy.net.validip.func_defaults = ('127.0.0.1', 8080) del _imp, _os, _sys, _path, _fp, _pathname, _description, _webpy, _replaceEt quand je dis plus que satisfaisante, je ne mâche pas mes mots. Voyez par vous même cet extrait de la sortie de pylint sur notre fichier (oui, j'ai une config pour pylint qui, entre autres, me permet de ne pas être embêté par l'absence de docstring ou par les noms de variables qui ne lui plaisent pas) :
Your code has been rated at 10.00/10Que demander de plus ? Oui, bon, d'accord : un exemple plus concret de l'usage de _replace. Ça tombe bien, parce qu'il y a autre chose qui m'énerve plus dans webpy que cette histoire d'adresse ip.
_webpy.webapi.input() est censée renvoyer les arguments GET et POST. On peut même préciser via l'attribut _method, si on ne veut que GET ou que POST par exemple. Sauf que quand on y regarde de plus prêt, webpy passe par cgi.FieldStorage() qui renvoie toujours les données GET, même quand on a demandé à n'avoir que les données POST, ce qui est assez génant. Étant donné que c'est _webpy.webapi.rawinput qui fait vraiment le travail, c'est elle que je vais remplacer.
import imp as _imp import os as _os import sys as _sys import urlparse as _urlparse _path = _sys.path[_sys.path.index(_os.path.dirname(__file__)) + 1:] _fp, _pathname, _description = _imp.find_module('web', _path) try: _webpy = _imp.load_module('web', _fp, _pathname, _description) finally: if _fp: _fp.close() def _replace(from_, to): def old(): pass if hasattr(from_, 'im_func'): from_ = from_.im_func for name in ('doc', 'name', 'defaults', 'code', 'globals'): attr_name = 'func_' + name setattr(old, attr_name, getattr(from_, attr_name)) setattr(from_, attr_name, getattr(to, attr_name)) from_.old = old def _rawinput(method=None, _parse_qsl=_urlparse.parse_qsl): if method and method.lower() == 'post': inputs = storage() for key, value in _parse_qsl(data(), True): inputs[key] = value return inputs return rawinput.old(method) _webpy.net.validip.func_defaults = ('127.0.0.1', 8080) _replace(_webpy.webapi.rawinput, _rawinput) del (_imp, _os, _sys, _urlparse, _path, _fp, _pathname, _description, _webpy, _replace, _rawinput)Du coup là, pylint est beaucoup moins content :
Your code has been rated at 5.16/10Ceci s'explique par le fait qu'on utilise storage, data et rawinput qui viennent tous les trois du contexte de la fonction qu'on remplace. pylint ne peut donc pas les connaitre. Si vraiment cela vous pose un problème, vous pouvez toujours passer _webpy en argument de la fonction _rawinput :
def _rawinput(method=None, _parse_qsl=_urlparse.parse_qsl, _web=_webpy): if method and method.lower() == 'post': inputs = _web.webapi.storage() for key, value in _parse_qsl(_web.webapi.data(), True): inputs[key] = value return inputs return _web.webapi.rawinput.old(method)Notez que l'on pourrait mettre « _webpy=_webpy » au lieu de « _web=_webpy ». Mais c'est sans compter sur pylint qui nous insulte parce que l'on ose redéfinir le _webpy global. Du coup avec cette version de _rawinput, on réobtient notre 10.00/10.
Voilà qui conclut notre petite expérimentation quant au remplacement à chaud de fonctionnalités de bibliothèques que l'on utilise mais nous posent problème. Je terminerai juste en rajoutant que l'on aurait aussi pu nommer notre fichier « quux.py ». Il aurait alors fallu l'importer avant toute utilisation de webpy (peu importe d'ailleurs si on l'importe avant ou après avoir importé webpy, l'important étant de le faire avant de l'utiliser). Passer par un fichier quux.py a un avantage (malgré le désavantage d'imposer un import en plus) : on peut de ce fait faire du monkey patching pour plusieurs bibliothèques à la fois sans devoir créer un fichier pour chacun d'entre elle. On peut même distribuer le fichier comme un véritable projet dépendant des bibliothèques qu'il patche.
UPDATE: ThibG m'a fait remarquer que j'aurai pu passer par types.FunctionType pour créer la fonction accueillant l'ancien code. Même si je ne suis pas très fan (principalement parce que ça nous fait un peu dupliquer des choses et parce qu'on ne peut même pas filer la docstring au constructeur…), voici ce que ça donnerait :
import types as _types def _replace(from_, to): if hasattr(from_, 'im_func'): from_ = from_.im_func for name in ('doc', 'name', 'defaults', 'code', 'globals'): setattr(from_, attr_name, getattr(to, 'func_' + name)) from_.old = _types.FunctionType(from_.func_code, from_.func_globals, from_.func_name, from_.func_defaults) from_.old.func_doc = from_.func_doc -
mercredi 26 octobre 2011 à 02:30:40
Le Python, l'Introspection et le Singe #1
J'inaugure avec ce billet une nouvelle série ayant pour thème l'introspection et le monkey patching avec python. Parfois didactique, souvent magique, cette série de billets aura pour but de vous faire partager certaines de mes découvertes et idées folles, qui ne sont pas forcément les bienvenues dans un vrai projet, mais qui toutefois sont assez jouissives à étudier (sur le plan intellectuel).
Si d'aventure vous tombez sur une bibliothèque python dont vous avez besoin mais dont certains détails vous insupportent, inutile d'aller coder la votre ou de la forker. Non, dites plutôt bonjour au monkey patching et à l'introspection. Mais attention, faites ça proprement. On n'est pas des singes non plus.
Prenons par exemple webpy (oui, je sais que ça s'appelle « web.py », mais je l'appellerai « webpy » dans le reste de l'article pour éviter la confusion avec le fichier que l'on va créer). Le point d'entrée pour cette bibliothèque est le module web. On va donc créer le fichier web.py que l'on va mettre directement dans le répertoire du projet utilisant webpy.
Passons au remplissage de ce fichier. On va d'abord récupérer une référence sur le module courant (notre web.py à nous), importer le module sys pour pouvoir manipuler sys.path et le module imp pour pouvoir importer webpy.
import imp as _imp import sys as _sys _here = _sys.path.pop(0) _fp, _pathname, _description = _imp.find_module('web') _webpy = _imp.load_module('web', _fp, _pathname, _description) _sys.path.insert(0, _here)Comme vous pouvez le lire, on va dans un premier temps récupérer le chemin vers le module web (qui est le nom du module principal de webpy). Pour cela, on a besoin de retirer le premier répertoire de sys.path de sorte à ce qu'il ne nous renvoie pas le chemin vers notre web.py. On va ensuite lui demander de nous charger ce module en lui donnant comme nom « web » et en le stockant dans la variable webpy. Et on finit par remettre le sys.path comme il était avant.
Cet import pourrait juste s'écrire « import web as _webpy » si on n'était pas justement en train de créer le fichier web.py. Il faut donc lui faire charger le bon module sans qu'il n'aille chercher le notre. On pourra remarquer au passage que l'on doit préciser le nom du module lors de l'appel de imp.load_module(). C'est ce qui servira à donner sa valeur à son attribut __name__. Attribut dont on peut changer la valeur à n'importe quel moment (sa seule vraie utilité est quand la méthode __repr__ d'un module est utilisée).
Pour en savoir plus sur imp.find_module() et imp.load_module(), je vous invite à consulter la documentation officielle du module imp .
La documentation de imp.load_module() nous apprend par exemple que si le nom qu'on lui donne correspond à un module déjà chargé, elle va agir comme reload(). Il est donc important ici de bien comprendre que le nom donné à imp.load_module() (j'insiste sur le nom de la fonction, parce qu'il en est autrement pour imp.find_module()) doit absolument être le même que le fichier dans lequel on se trouve. Ainsi, python croira qu'on lui demande de recharger le module courant mais en utilisant un autre fichier. Ceci aura pour effet de peupler l'espace de noms web avec le contenu de webpy.
On a donc atteint la moitié de notre objectif. À savoir, créer un module qui se fasse entièrement passer pour webpy. Ainsi, on peut déjà utiliser notre web.py comme s'il sagissait de webpy.
Il ne nous reste alors plus qu'à ajouter/altérer/remplacer les fonctionnalités que l'on veut. Mais attention, il faut bien comprendre que ce que l'on va modifier ne le sera que pour l'application utilisant webpy. Les changements ne seront pas forcément effectifs pour webpy lui même.
Prenons par exemple, quelque chose que je déteste chez webpy : le fait que par défaut son mini serveur http écoute sur 0.0.0.0 alors que moi je préférerais qu'il se contente de 127.0.0.1. À chaque fois que je me remets à travailler sur un projet utilisant webpy, je suis obligé de penser à rajouter 127.0.0.1 sur la ligne de commande pour qu'il ne serve effectivement que dessus. J'aimerai bien ne plus avoir à le faire. Après un rapide coup d'œil au code de webpy, je me rends compte que tout se joue dans la fonction web.net.validip().
def _validip(ip, defaultaddr='127.0.0.1', defaultport=8080, _old=_webpy.net.validip): return _old(ip, defaultaddr, defaultport) _webpy.net.validip = _validipCeci fonctionnera parfaitement bien si dans notre projet on utilise web.net.validip(), ou bien si quelque chose de web.net l'utilise. Par contre, dans le cas qui m'intéresse, web.net.validip est importé dans web.wsgi avant que je ne puisse faire la substitution. Du coup, je n'ai modifié qu'une seule référence. Hors, il faudrait au moins modifier web.wsgi.validip, voire même toutes les références (histoire d'avoir un code cohérent). Pour faire simple, je vais juste me contenter de modifier le code donné plus haut pour l'adapter à mon réel besoin. Vous remarquerez d'ailleurs au passage que de ce fait, je n'ai plus besoin de rajouter une référence vers l'ancienne fonction vu qu'elle est toujours en place.
def _validip(ip, defaultaddr='127.0.0.1', defaultport=8080): return _webpy.net.validip(ip, defaultaddr, defaultport) _webpy.wsgi.validip = _validipSi je récapitule tout, on obtient quelque chose comme :
import imp as _imp import sys as _sys _here = _sys.path.pop(0) _fp, _pathname, _description = _imp.find_module('web') _webpy = _imp.load_module('web', _fp, _pathname, _description) _sys.path.insert(0, _here) def _validip(ip, defaultaddr='127.0.0.1', defaultport=8080): return _webpy.net.validip(ip, defaultaddr, defaultport) _webpy.wsgi.validip = _validipJe ne sais pas vous, mais moi je ne suis pas totalement satisfait avec ce code. Si MsieurHappy était là, il me dirait qu'il n'est pas assez warrior. Et, aussi exceptionnel que cela puisse être, il aurait raison !
Je n'aime vraiment pas cette histoire de fonction que l'on ne peut remplacer qu'en sachant nous même où elle est importée. Je me suis donc fendu d'une petite fonction qui va faire le travail à notre place.
def _replace(module, from_, to, processed=None, ismodule=inspect.ismodule): if processed is None: processed = list() if module in processed: return processed.append(module) for name in dir(module): attr = getattr(module, name) if ismodule(attr): _replace(attr, from_, to, processed) elif attr is from_: setattr(module, name, to)Cette fonction, que je ne détaillerai pas étant donné que c'est juste un simple parcours récursif, s'appelle avec le module de base (dans notre cas, webpy), une référence vers la fonction que l'on cherche à remplacer, ainsi qu'une référence vers la fonction par laquelle on doit remplacer. Ainsi, on peut remplacer « _webpy.wsgi.validip = _validip » par « _replace(_webpy, _webpy.wsgi.validip, _validip) ». Malheureusement, on doit réutiliser le coup du _old dans la fonction _validip (parce que sinon on n'aurait plus aucune référence dessus).
En nettoyant un peu l'espace de noms des symboles inutiles, voici ce qu'on obtient au final pour notre fichier web.py :
import imp as _imp import inspect as _inspect import sys as _sys _here = _sys.path.pop(0) _fp, _pathname, _description = _imp.find_module('web') _webpy = _imp.load_module('web', _fp, _pathname, _description) _sys.path.insert(0, _here) def _replace(module, from_, to, processed=None, ismodule=_inspect.ismodule): if processed is None: processed = list() if module in processed: return processed.append(module) for name in dir(module): attr = getattr(module, name) if ismodule(attr): _replace(attr, from_, to, processed) elif attr is from_: setattr(module, name, to) def _validip(ip, defaultaddr='127.0.0.1', defaultport=8080, _old=_webpy.net.validip): return _old(ip, defaultaddr, defaultport) _replace(_webpy, _webpy.net.validip, _validip) del _imp, _inspect, _sys, _here, _fp, _pathname, _description, _webpy, _replace, _validipÀ noter que l'on peut aussi remplacer une classe de la même manière. Bien que dans ce cas on préférera peut-être la modifier en place plutôt que d'en créer une nouvelle.
D'ailleurs, on aurait aussi très bien pu modifer la fonction en place sans devoir recourir à la fonction _replace actuelle. En effet, la version actuelle de cette fonction considère qu'une fonction est immuable. Or ce n'est pas le cas. On peut par exemple accéder à son code (pas sous forme exploitable par contre), à ses valeurs par défaut, etc. La documentation officielle de python pour le module inspect donne la liste complète des choses intéressantes.
Mais ceci fait l'objet d'un autre billet dans lequel je parle aussi de la modification de sys.path qui n'est pas optimale (on ne peut par exemple pas mettre notre fichier web.py ailleurs que là où est situé le projet l'utilisant).
Si vous n'avez pas de quoi tester notre fichier, je vous invite à vous rendre sur la page d'accueil du site de webpy qui contient un petit hello world. Testez ce fichier dans un coin (webpy affichera « http://0.0.0.0:8080/ » dans la console), puis retestez avec notre fichier dans le même répertoire (là webpy affichera « http://127.0.0.1:8080/ »).
-
samedi 21 mai 2011 à 23:45:59
10 mauvaises raisons de passer à firefox 4
- Les fuites mémoires sont encore au rendez-vous.
- Il s'intègre très bien dans un bureau nazi gnome.
- Interface utilisateur une nouvelle fois cassée. Idéal pour ceux aimant apprendre de nouvelles choses encore et encore.
- Meilleur support de HTML 5^H.
- Il ne reste plus beaucoup de temps pour en profiter, la 5.0 est annoncée pour juin.
- La 6.0 devant sortir dans quelques mois seulement, il n'y aura pas beaucoup de temps de profiter de la 5.0, ce qui réduit nécessairement le temps durant lequel on pourra profiter de la 4.0.
- La 7.0 devant sortir avant la fin de l'année, il n'y aura pas beaucoup de temps pour profiter de la 6.0, ce qui réduit nécessairement le temps durant lequel on pourra profiter de la 5.0. Et cela réduit d'autant plus le temps durant lequel on pourra profiter de la 4.0.
- Panorama qui vous permettra enfin de pouvoir rentabiliser votre GPU. Oui, parce que y'en a marre qu'il n'y en ait toujours que pour la RAM.
- Certifié obsolète par Link Mauve.
- Tristan Nitot est toujours président de Mozilla Europe.
-
jeudi 10 mars 2011 à 14:49:49
7DRL 2011: Reflections on maps structure
I had an epiphany three days ago, and I could not stop thinking about it since. I realized that dungeon was nothing more than a graph. It does seem to say anything like that, but there are a lot of implications.
This is not a new idea. Others have already spoken before me. For example, Steve Segreto (based on an original work of David Adam) assumes that each cell is a node. A cell in the middle of a room is connected to 8 other cells. This representation gives a lot of nodes and edges. I personally find that it gives too much.
Two reasons make me say this. The first is that algorithms who need to travel many times the graph will have their execution time too long to be reasonable. Do not forget that the maps should not put an eternity to generate. The second reason is that we lose information about the structure of the dungeon itself. We lose the concept of rooms/tunnels. But I find her particularly interesting.
Let's take the example of a monster that is somewhere in the dungeon and tried to reach the player. To do this, consider the Dijkstra pathfinding algorithm. It needs to traverse the entire graph to find a solution. As a result, the execution time can quickly become substantial if the graph is immense. Moreover, once in a room, go to the next tunnel, the shortest route proves to be a straight line (with Bresenham example). Dijkstra's no need to know that. It's the same for tunnels. Once in, there is no real surprise to get to the other side. This representation does not take that into account and we will have to run Dijkstra every time the monster will move one cell. We quickly realize how this representation is expensive. And here it is assumed that there is only one monster that follows the player. Imagine with several…
The way I see a dungeon addresses these issues. Rather than from the fact that cells are the nodes of the graph, I consider that the rooms themselves are the nodes and tunnels are edges. This implies several things. First, the graph is greatly simplified. It has indeed many fewer nodes and a lot less edge. Dijkstra will therefore act to a higher level of abstraction and go faster. He does not calculate the path himself inside a room when he wants to go from one edge to another. Just use a simplified version of Bresenham who give us only the next cell where to go (without having to place the algorithm in full). It's the same for tunnels.
It should be noted that unlike the first representation, the one I propose implies that the cost of the edges is not the same whatever the edge. Indeed, the tunnels do not have the same length and the rooms do not have the same size. We must take this into account during the exploration of the graph. We can already count the number of cells in a tunnel to find the cost of an edge. But it does not include the size of the room. I have not yet found a miraculous solution, but the fairest is to consider a tunnel from the middle of a room to go to the middle of another room. It should therefore, in addition to the number of cells in the tunnel itself, add the number of cells needed to reach the middle of each room that the tunnel connects.
We must also pay attention to the case of tunnels that have branches. Such tunnels will not link only two rooms, but a variable number. One solution might be to avoid such tunnels or consider branching points as pseudo-rooms of size 1 × 1.
Whichever representation is chosen, it is pleasing to note that this allows us to do certain things made totally impossible if we just see a dungeon as a 2D matrix. For instance we can manage to put the maximum distance between the player and the exit (to prevent him from having to finish the level seen just a single room). But it can also be used to generate the dungeon. We construct a graph, and there is actually a dungeon in creating the 2D matrix represents. Although for this example, the second representation is more appropriate.
Well… I have yet push the thinking at the end, but I do see advantages to represent the dungeons as graphs where rooms are nodes and tunnels are edges.
-
jeudi 10 mars 2011 à 13:46:33
7DRL 2011: Anauroch Step 7-9
The three past days have not been very productive. In fact, I spent a lot of time thinking about an idea I had, rather than coding (an idea that gave rise to another post). But this does not mean that I have not advanced.
I could work on the step 7 which is about create a basic combat system. We can fight against monsters. Once they have no more hit points, they disappear. But the player can not die yet. His life points go in the negative. It's just an ease of development to test the game more easily.
For the step 8, I created data files for monsters. In addition to outsource hardcoded data, it allowed me to easily add a new type of monster. I will just have to create more (because two is not really enough). I also took the opportunity to create a class that manages the dice. So the damage a monster can do is not anymore a constant value but a dice like 1d4+1. It's the same for its hit points. All this helps strengthen the randomness of the game, and brings some consistency that strengthens the whole.
Currently I am trying to take care of the step 9. I started by placing (false) items on the map and allow the player to pick them up. I then managed to display the inventory. I'm rather pleased with myself on this one, because with very few lines, I have a very acceptable result. ncurses really deserves that I'm interested more in it. For example, I could create another window in addition to the main, display it above the base window, then close the new window and return to the one below without having to completely redraw myself, as does X. And it's very nice.
As can be seen in the screenshots below, in addition to the display of the inventory, I also managed that the player can throw items. I took care to use a color code for both displays, which although identical, have very different uses.
The next step is to create real items and to use them, equip them, etc.
-
lundi 7 mars 2011 à 14:52:41
7DRL 2011: Anauroch Step 4-6
I have hardcoded a simple map with tuple of string (one string per line). I literally display this structure on the screen (in fact each entry in the tuple is a line on the screen). Collisions are a piece of cake because I juste have to test the content of map[y][x] (a '#' for wall, and '.' for floor). But in python a string is an immutable object. So when I have added some doors, I could not simply make them open in the current structure. So I had to change the map structure. It's now a list of list of Cell (it is a class containing a type like wall, floor or door).
In the fifth step, we should add save/load feature. But I don't want to implement it yet because I think it goes against the principle of permadeath. Maybe I will change my mind later, but meanwhile I will just put this step aside.
The sixth step is about monsters. Just after the map creation, I instantiate some monsters and I put them randomly on the floor. For now they can only move randomly on empty floor cells (so it is impossible for monsters to be on the same cell at the same time).
So for now, I have an hardcoded map with monsters and doors. Monsters can move and we can open doors. The next step will be about monsters AI (to chase the player) and combat system.
-
dimanche 6 mars 2011 à 16:44:02
7DRL 2011: Anauroch Step 1-3
I have just finished the step 3 of the How to Write a Roguelike in 15 Steps guide.
First I have started with the Python HOWTO Curses Programming with Python and the API documentation. I have already done some basic testing with ncurses but never did a full application. Although the HOWTO is not complete, it is enough to start.
Then I've made a title screen. As you can see on the screenshot, I have used toilet with the font letter to render the game name. It's pretty simple but it's doing the job.
Last I've added a yellow @ which is movable with the keypad or directional buttons. For now it's like a snail because he leaves a trail of slime behind him. We can move him in the height directions like any other roguelike.
I am very pleased to have completed this step so quickly. I do not doubt my abilities, but I thought it would take more time because of my learning of ncurses. Well… But there is not something to brag about. I still have a long way to go before it can claim to be a roguelike.
-
dimanche 6 mars 2011 à 12:03:39
7DRL 2011: Anauroch
I have decided to participate to 7DRL Contest 2011. The 7DRL Challenge is an event where everyone is challenged to create a roguelike in a one-week span.
It will be the first time I write a roguelike. I am not new to this game type, but I have never tried to write one. I think it will be very interesting especially because I will start from nothing. I just have emacs and python. I will try to follow the How to Write a Roguelike in 15 Steps guide as much as I can.
I already found a name for the game (I can't write code for a project without a name): "Anauroch". I still have to write it.
I am starting right now (Sunday, 11h00 UTC). Good luck to other participants (and don't forget to sleep).
-
vendredi 18 décembre 2009 à 15:33:39
Nouveaux paquets debian dans sid #3
Bien que le nombre de nouveaux paquets soit en constante augmentation, il y a eu moins de nouveaux jeux dernièrement que ce qu'il pouvait y avoir avant. J'en profite d'ailleurs pour féliciter Miriam Ruiz qui est la développeuse Debian grâce à qui on doit la création de la Debian Games Team mais aussi l'entrée de nombreux jeux (notamment ceux de Kenta Cho, aka monsieur D). Elle fait vraiment un travail remarquable.
Parmi les nouveaux paquets, j'ai cette fois-ci découvert une véritable perle. Suivant le conseil de Paco, je lui dédierai un billet entier.
Voici donc la liste des quelques paquets, classés par catégorie, qui ont retenu mon attention ces 3 derniers mois :
- admin
- apt-offline : Permet de mettre à jour sa debian sans avoir de réseau à porté de câble. Grâce à lui on génère un fichier représentant l'état actuel du système. Sur une autre machine ayant le réseau (et pouvant être sous windows), on récupère une archive zip. De retour sur la machine d'origine, on installe l'ensemble des mises à jour grâce à l'archive. Pour plus de détails et un exemple, veuillez vous reporter à l'article du site Debian Administration sur apt-offline.
- aptdaemon : Démon pour APT. Il permet de pouvoir mettre à jour la liste des paquets disponibles sur les dépôts, de mettre à jour le système, d'installer et de désinstaller des paquets au travers d'un client et tout ceci en étant un simple utilisateur.
- aptitude-gtk : Aptitude 0.6 est enfin entré dans sid. Et avec lui nous arrive l'interface graphique en GTK tant attendue. Bien que fort prometteuse, je lui trouve néanmoins encore trop de défauts pour être réellement utilisable dans la vie de tous les jours. Vivement que le projet mûrisse encore un peu. Parce qu'il a vraiment le potentiel pour remplacer synaptic à long terme.
- execstack : Permet de modifier ou d'ajouter l'entête GNU_STACK à un binaire ELF. Pour plus d'informations sur GNU_STACK, je vous invite à lire une documentation de gentoo sur le sujet qui explique très bien ce dont il s'agit.
- gpaco : Interface graphique pour le paquet paco.
- hwloc : Permet d'avoir une vue hiérarchique de son système.
- hwloc-nox : Comme hwloc, mais fonctionnant sans X.
- media-player-info : Base de données regroupant des informations sur les systèmes de fichiers de lecteurs multimedia. On peut par exemple y trouver comment sont organisés les fichiers sur tel ou tel modèle. Ainsi les applications peuvent savoir dans quel répertoire mettre la musique, ou dans quel autre mettre les vidéos, etc.
- paco : Quand on installe un programme avec les très célèbres « ./configure », « make » et « make install », on se retrouve généralement avec un logiciel ininstallable proprement (le « make uninstall » étant pour ainsi dire inexistant). Paco propose de régler ce soucis en lançant lui même la commande « make install ». Il va ainsi pouvoir enregistrer la liste des fichiers installés. il pourra donc par la suite désinstaller proprement ces applications. À noter que ce genre d'outil s'avère extrêmement pratique lors de la construction d'un système LFS. Il y a d'ailleurs des tutoriels sur le site officiel qui expliquent comment s'y prendre.
- policykit-1 : Boîte à outils permettant de gérer la politique de communication entre des processus non-privilégiés et des processus privilégiés. Pour par exemple permettre de pouvoir faire un mount sans devoir passer root.
- devel
- clang : Nouvelle interface c, c++, objective c et objective c++ pour llvm.
- ldc : Compilateur D basé sur llvm.
- mercurial-buildpackage : Utilitaire permettant d'automatiser la maintenance de paquet Debian en utilisant mercurial.
- mercurial-server : Si l'on veut passer par ssh pour accéder à un dépot mercurial, il nous faut obligatoirement un compte utilisateur sur la machine cible. Mais cela pose plusieurs problèmes. mercurial-server se propose de les résoudre. Tout d'abord, il lui faut juste un compte utilisateur et un répertoire home associé pour gérer l'ensemble des personnes pouvant interagir avec l'ensemble des dépôts co-existants sur le serveur. L'authentification se passe par clef ssh. L'administrateur du serveur gère ensuite les différentes permissions d'accès depuis un dépôt mercurial. On veut permettre à un nouvel utilisateur d'utiliser un dépôt ? Très bien, on ajoute sa clef ssh sur le dépôt des utilisateurs, on fait un commit et un push, et c'est réglé. On veut au contraire enlever un utilisateur ? On retire sa clef du dépôt, on fait un commit et un push, et c'est réglé. Administrer des utilisateurs pour des dépôts n'a jamais été aussi simple.
- mutextrace : Outil permettant de suivre l'évolution de mutex dans une application multi-thread. Elle s'avère très utile pour débugger un tel programme pour des petits besoins ou quand les ressources sont limitées.
- tortoisehg : Utilitaire permettant d'intégrer mercurial dans son gestionnaire de fichiers et ainsi gérer un dépôt mercurial avec la souris. Pour l'instant il ne le fait qu'avec nautilus grâce au paquet tortoisehg-nautilus
- uclibc-source : Sources de uclibc. Il s'agit d'une implémentation de la bibliothèque standard du C qui est plus petite que glibc. Cela s'avère très pratique dans le cadre de systèmes embraqués.
- xul-ext-webdeveloper : Extension pour firefox totalement indispensable lorsque l'on fait du développement web.
- editors
- editra : Éditeur de texte multi-plateforme. Il gère la coloration syntaxique, permet de lancer des commandes shell, utilise WxWidgets (donc le rendu sous GNU/Linux est fait avec GTK), est fait en Python et est totalement indépendant d'un quelconque gnome ou kde.
- games
- colorcode : Clone de mastermind en Qt.
- rlvm : Implémentation libre de l'interpréteur de Visual Art's. L'implémentation officielle est notamment utilisée pour les jeux de Key comme Air, Kanon ou bien encore l'excellentissime Clannad. Pour rappel, ThibG avait commencé un fork de xclannad (une autre implémentation libre, mais abandonnée) et l'avait baptisé OtakuNoRaifu.
- wormux-servers : Ce paquet permet de créer son propre serveur pour wormux.
- xcowsay : Ce paquet est la version graphique du paquet cowsay. Spéciale dédicace à xbright.
- graphics
- fim : Véritable couteau suisse pour la visualisation, ce logiciel permet de visionner des images sous X en passant par SDL, ou bien sans X en passant par le framebuffer. Il permet entre autres aussi d'avoir une sortie en ascii-art (grâce à aalib).
- haskell
- arbtt : Utilitaire permettant de voir à quoi l'on passe le plus clair de son temps. Il va de lui même analyser les données qui lui sont accessibles sans que l'on ait besoin de lui indiquer manuellement ce que l'on fait. Il va par exemple regarder quelles sont les fenêtres allumées et actives.
- libdevel
- stx-btree-dev : Implémentation d'arbre B+. Conçu pour remplacer les conteneurs set, map, multiset et multimap de la STL, il reste très proche de leur interface. Une démo est fourni dans le paquet stx-btree-demo.
- libs
- libcsfml-*1.5 : SFML est une bibliothèque écrite en C++ utile lorsque l'on a veut manipuler des images, du son, le réseau, etc. Ces paquets permettent de l'utiliser depuis un code C. Voici la liste complète de ces paquets gérant chacun un aspect différent de SFML : libcsfml-audio1.5, libcsfml-graphics1.5, libcsfml-network1.5, libcsfml-system1.5 et libcsfml-window1.5.
- libmagickcore2-extra : Le support de SVF, WMF, OpenEXR, DjVu et Graphviz pour imagemagick disposent maintenant d'un paquet qui leur est propre.
- mail
- bmf : Filtre Bayesian pour les emails. L'utilisateur l'entraine à faire la différence entre ce qui est du spam et ce qui n'en est pas. Il s'intègre très bien avec procmail et mutt (mais pas seulement). Il gère plusieurs formats de stockage et est fourni avec un utilitaire permettant la conversion entre ces différents formats.
- claws-mail-python-plugin : Extension permettant de faire des scripts en Python pour claws-mail.
- xcite : Gestionnaire de citations pour emacs. On associe une citation à une personne, et il peut nous ressortir les citations associées à cette personne.
- xul-ext-traybiff : Extension pour thunderbird permettant d'avoir un système de notification pour lorsque l'on reçoit de nouveaux mails via une icone dans le systray.
- misc
- stx-btree-demo : Démo d'utilisation du paquet stx-btree-dev.
- net
- belier : Véritabe couteau suisse dès lors que l'on doit passer plusieurs machines pour se connecter en ssh. Jusqu'à présent, on devait se connecter à la première machine, puis de là, à la seconde, ainsi de suite jusqu'à arriver à la machine désirée. Par exemple à ma fac, pour me connecter à une machine en dehors du réseau de la fac, je dois d'abord me connecter sur le serveur qui fait office de proxy, puis seulement là je peux me connecter sur la machine distante voulue. belier permet d'avoir à éviter de faire les manipulations soit même qui peuvent être fort contraignantes lorsque l'on doit faire cette manipulation régulièrement. Pour cela, il va générer un script shell que l'on aura plus qu'à utiliser directement quand on voudra se connecter sur cette fameuse machine distante. Il demande les mots de passe un à un (sauf s'ils sont précisés lors de la création du script), sans que l'on ait besoin de taper les différentes commandes. Je vous invite à consulter le billet d'un développeur Debian concernant ce logiciel qui en résume plutôt bien toutes les possibilités offertes.
- torsocks : Ce paquet s'avère utile lorsque l'on est un fanboy de tor. Il s'assure que les reqêuetes DNS sont gérées de manière sûre et il rejette explicitement tout traffic UDP de la part des applications.
- uget : Voici quelqu'un qui a eu la même idée que moi. Avoir un gestionnaire de téléchargement en GTK. Il permet de reprendre un téléchargement interrompu, de mettre des téléchargements sur liste d'attente, de classer les téléchargements par catégories, de s'intégrer avec firefox via l'extension flashgot, d'importer des téléchargements depuis des documents html, etc.
- otherosfs
- python
- pep8 : Utilitaire en ligne de commande permettant de vérifier la conformité de son code par rapport à la PEP8. Tout programmeur Python qui se respecte devrait utiliser ce genre d'outil lors de développement d'applications.
- pyjamas : Permet d'écrire des applications JavaScript en Python.
- python-aptdaemon : Module Python pour utiliser aptdaemon depuis un programme en Python.
- python-aptdaemon-gtk : Widgets GTK pour utiliser aptdaemon.
- python-bottle : Framework WSGI pour Python.
- python-dingus : Un dingus ressemble à un objet mock à la différence près qu'on ne définit pas nos attentes avant de l'utiliser. On exécute notre programme, on utilise un dingus à la place de n'importe quel autre objet ou classe, et il va enregistrer tout ce qui lui arrive. Ensuite quand le programme est fini, on peut faire des assertions par rapport à ce que le dingus a subi.
- python-execnet : Outil facilitant la distribution de tâches sur un réseau, la création d'applications reposant sur l'utilisation de plusieurs processus, la création de scripts pour administrer des parcs informatiques, etc. Pour résumer, il permet de casser les barrières du réseau, des plateformes et des différentes versions/implémentations de Python.
- python-iniparse : Parseur de fichier INI. Il assure une compatibilité ascendante avec ConfigParser. Il préserve la structure des fichiers INI (l'ordre des sections et des options, l'indentation, les commentaires, les lignes vides, etc) quand on les modifie. Il permet aussi d'accèder aux différents éléments avec une notation à base de points (foo.bar.baz) ou comme s'il s'agissait de dictionnaires (foo['bar']['baz']). Cette façon d'accèder aux données est vraiment très intéressante. Je l'utilise moi même dans plusieurs de mes projets. Je vous invite à consulter les nombreux exemples disponibles sur le site officiel et qui mettent très bien en avant toute la puissance du bousin.
- python-pudb : Debugger Python en console. Même si ce genre d'outil peut s'avérer très pratique, il faut cependant avouer que pour le moment ce n'est pas très sexy. Gageons qu'il y aura une interface en GTK dans un futur plus ou moins proche.
- python-slimmer : Outil permettant d'optimiser/compresser des documents (x)html et css.
- python-stdeb : Outil permettant la création de paquets sources Debian depuis un paquet Python.
- trac-graphviz : Extension pour Trac permettant de faire des graphes pour le wiki avec un rendu fait par graphviz.
- science
- libstxxl1 : Bibliothèque C++ proposant une alternative à la STL permettant de gérer d'énorme quantité de données (de l'ordre de plusieurs téraoctets).
- sound
- arename : Utilitaire permettant de renommer intelligemment des fichiers musicaux d'après les tags du fichier. Il est possible de définir son propre format pour le nom de destination.
- freedesktop-sound-theme : Ensemble de sons volés de gnome-audio, KDE, Ekiga, Pidgin, ALSA et rassemblés pour former un thème de son XDG. Se marie bien avec libcanberra.
- oss4-base : OSS fait son grand retour dans Debian.
- oss4-gtk : Mixer pour OSS utilisant GTK.
- oss4-source : Sources pour les différents modules noyau pour OSS. À noter aussi l'entrée du paquet oss4-dkms.
- text
- blahtexml : Utilitaire permettant de convertir des équations écrites avec TeX vers MathML.
- utils
- comprez : Décidément, encore un qui a eu la même idée que moi… Il s'agit d'un script shell qui sert d'interface pour l'ensemble des programmes de compression. « comprez foo.tar.bz2 » va automatiquement décompresser l'archive comme il faut et sans que l'on ait besoin de préciser quoi que ce soit. Il en va de même lorsque l'on veut créer une archive. Ce genre d'outil s'avère fort pratique pour un novice ou pour toute personne étant un peu lasse de toujours devoir taper des lignes de commandes différentes pour toujours faire la même chose (créer et décompresser des archives dans des formats différents).
- envstore : Permet de sauvegarder les variables d'environnement, de les consulter et de les remettre dans le shell.
- furiusisomount : Permet de monter facilement des images ISO. Il gère les formats ISO, IMG, BIN, MDF et NRG. Il crée le point de montage tout seul, fait le ménage tout seul dès que l'image est démontée, tient à jour un historique des 10 dernières images montées, etc.
- keyboard-configuration : L'été dernier a amené une nouvelle version de X et de la gestion du clavier aussi bien avec X qu'en console. De fait, il n'était plus si évident que ça de s'y retrouver pour le configurer. Mais grâce à ce nouveau paquet, la configuration du clavier est maintenant centralisée dans un seul fichier : /etc/default/keyboard. Le contenu de ce fichier ressemble à ce que l'on trouvait avant dans le fichier de config de X. Il est donc très simple à personnaliser. D'autant que certains seront ravis de voir que par défaut il y a ce qu'il faut dans ce fichier pour que la combinaison ctrl+alt+backspace fonctionne de nouveau.
- nasty : Utilitaire permettant de retrouver sa passphrase GPG.
- xtitle : Permet de fixer le titre de la fenêtre pour le xterm dans lequel il est lancé.
- xz-utils : Outil en ligne de commande pour utiliser xz qui est le successeur de lzma.
- video
- ffprobe : Outil en ligne de commande permettant d'avoir des informations sur un fichier multimedia ou sur un flux. Il est basé sur FFmpeg.
- transmageddon : Permettant de passer un fichier d'à peu près n'importe quel format multimedia vers n'importe quel autre format multimedia. Très pratique lorsque l'on doit avoir les vidéos ou musiques dans un format très précis pour notre lecteur multimedia.
- web
- trac-customfieldadmin : Permet de rajouter et de gérer des champs supplémentaires via l'interface d'administration de trac sans devoir éditer le fichier trac.ini à la main.
- trac-mastertickets : Permet de mieux gérer les billets bloqués par d'autres. On peut maintenant dire si un billet est bloqué par tel ou tel autre, et aussi voir si un billet en bloque d'autres.
- trac-wysiwyg : Permet d'éditer n'importe quel textarea avec un éditeur WYSIWYG.
- trac-xmlrpc : Propose une interface xmlrpc pour agir sur l'instance du trac. Comme par exemple ouvrir ou fermer des tickets.
- xul-ext-adblock-plus : Paquet pour l'extension adblock-plus pour iceweasel. Parce qu'un web sans pub est un web meilleur.
- xul-ext-firecookie : Extension pour iceweasel permettant de gérer plus finement les cookies.
- xul-ext-firebug : Extension pour iceweasel très utile dans le cadre de développement web.
- xul-ext-flashblock : Extension pour iceweasel destiné à bloquer les conneries en flash. Totalement inutile lorsque l'on utilise NoScript. D'autant plus lorsque comme moi, on n'a de toute façon pas de quoi lire les animations flash.
- xul-ext-greasemonkey : Paquet pour l'extension adblock-plus pour iceweasel.
- x11
- cairo-dock : Dock utilisant cairo pour le rendu et glitz pour l'accélération matérielle. Il peut être étendu par des extensions et peut aussi servir de barre de tâches.
- windowlab : Gestionnaire de fenêtre ressemblant à celui d'amiga. Il se dit simple et rapide. Au vu d'un screenshot officiel, je me demande ce que PycaWM peut lui envier.
- xscreensaver-screensaver-bsod : Écran de veille affichant des BSOD de divers systèmes d'exploitation. Je vous invite à prendre connaissance du warning qui apparait dans la description du paquet.
- xfce
- xfce-keyboard-shortcuts : Paquet contenant la liste des raccourcis clavier par défaut de xfce.
- xfce4-volumed : Permet de contrôler le volume grâce aux touches multimedia quand on utilise xfce.
- admin
-
dimanche 27 septembre 2009 à 04:45:32
Nouveaux paquets debian dans sid #2
Beaucoup de nouveaux paquets entrent dans debian chaque mois, et malgré tout, très peu retiennent mon attention. Je constate avec un certain dégoût que mono s'immisce de plus en plus. Quand je pense à tout ce temps perdu à rien qui pourrait être investi de manière beaucoup plus intelligente…
Les nouveaux paquets java ne sont pas non plus en reste. C'est assez dommage, parce que parfois les projets ont l'air intéressant. Mais le langage utilisé les discrédite immédiatement.
À l'occasion je ferais un billet pour parler plus en profondeur de tout ceci. Mais en attendant, voici donc la liste des quelques paquets, classés par catégorie, qui ont retenu mon attention ces 4 derniers mois :
- admin
- cdebconf-gtk : Interface graphique en GTK pour cdebconf.
- computer-janitor : Outil en ligne de commande permettant de donner une nouvelle fraîcheur à son système. Il permet entre autres de supprimer les fichiers inutiles comme les .dpkg-old, les paquets inutiles, etc.
- computer-janitor-gtk : Interface graphique en GTK pour computer-janitor. À noter qu'elle dépend d'une partie de gnome, en l'occurence gksu (et ses dépendances). On est toutefois en droit de se demander pourquoi une telle dépendance est nécessaire quand on sait que l'application nous insulte si on ose la lancer sans être root et qu'elle freeze tout de suite après.
- gadmintools : Permet d'administrer des services comme bind, dhcpd, openvpn, proftpd, rsync, samba et squid directement depuis une interface graphique en GTK.
- grub-efi-amd64 : Version spéciale de grub fonctionnant avec EFI-AMD64.
- grub-efi-ia32 : Version spéciale de grub fonctionnant avec EFI-IA32.
- gufw : Interface graphique en GTK pour ufw. À noter qu'elle dépend de libgnome2-0…
- imvirt : Script perl permettant de détecter si l'on est dans un environnement virtuel. La version actuelle gère VirtualBox, Virtual PS/Server, VMWare, QEMU, KVM, Xen et quelques autres.
- iptables-persistent : Permet de garder les règles iptables entre deux redémarrages.
- kalternatives : Interface graphique en QT et dépendant de KDE pour configurer les alternatives.
- nagzilla : Robot jabber faisant office de relay. Typiquement il va se loger dans un salon et va ensuite répéter tout ce qui y sera dit sur un autre salon ou à une personne.
- supervisor : Se présentant comme n'étant pas un remplaçant de init, il dispose cependant de fonctionnalités similaires. Entre autres, il va pouvoir lancer et éteindre tout un groupe de processus dans un ordre bien précis, mais aussi permettre le crontrôle des processus via un mechanisme RPC. Un utilisateur pourra ainsi redémarrer des processus.
- xmount : Outil permettant d'avoir un système de fichiers virtuel à partir d'un système de fichiers existant. Je vous invite à consulter la description du paquet pour en savoir plus.
- devel
- explain : Outil permettant de connaître la signification des erreurs des appels systèmes.
- gtkparasite : Outil s'intégrant directement dans notre application. Il permet de récupérer un grand nombre d'information sur les fenêtres, comme leur hierarchie et les propriétés des widgets. Il nous permet aussi de changer la logique del 'application en pleine utilisation.
- kwstyle : Outil censé analyser la consistence d'un code source en C/C++ écrit par plusieurs personnes et dire s'il l'ont pourrait croire que le code n'a été écrit que par une seule personne (en se basant sur la façon dont chaque bout a été codé). Je n'ai pas contre pas compris comment il fallait s'en servir…
- editors
- emacs23 : Éditeur de texte de prédilection de toute personne qui se respecte. La version 23 apporte pas mal de nouveautés. Je vous recommande vivement d'y jeter un œil si ce n'est pas déjà fait.
- games
- angband : Roguelike game utilisant SDL pour le rendu.
- ember : Client pour le projet Worldforge. Même si c'est très prometteur, je reste quand même très déçu. Le projet n'est toujours pas « jouable » alors qu'il date de 1997.
- gearhead2 : « Roguelike mecha role playing game in space ». Un siècle et demi après une guerre nucléaire, plusieurs factions se battent pour déterminer le futur de la race humaine. Il s'agit de la suite de GearHead 1, qui se déroule 5 ans après. Le jeu est encore en développement. À noter que le mecha que l'on contrôle est extrêment personnisable. À noter aussi que GearHead 1 est aussi disponible dans debian sous le nom « gearhead ».
- glhack : Version SDL/OpenGL de NetHack. À noter qu'il ne sagit pas de la première tentative.
- gnuminishogi : Logiciel permettant de jouer au minishogi, une variante du shogi sur un plateau de 5×5.
- mupen64plus : Émulateur pour Nintendo 64 proposant un système de greffon. Il permet entre autres de charger des roms compressées, de sauvegarder plusieurs états, de passer en plein écran, d'utiliser un système de triche et d'utiliser des packs de textures plus grande résolution.
- tetzle : Jeu permettant de générer un puzzle à partir d'image nous appartenant. Bien que très simple au final, il se révèle très prenant quand on comment à prendre des grandes images et à demander un nombre de pièces assez conséquent. Gros soucis par contre, et pas des moindres, il passe par OpenGL et utilise Qt pour la gui…
- zaz : Puzzle game aussi dur que prenant.Une longue file indienne de boules se déplacent le long d'un chemin. On peut en prendre une et la remettre à un autre endroit. Une fois que l'on en a au moins trois côte à côte, elles disparaissent. Le but est de faire disparaître toutes les boules avant qu'elles n'aient eu le temps d'arriver à leur destination. À noter que le jeu a besoin de l'accélération 3D.
- gnome
- gconf-cleaner : Parce que sortir les poubelles n'est pas du luxe. Le mieux étant bien entendu de pouvoir se passer totalement de gconf…
- graphics
- libs
- libass4 : Bibliothèque permettant de manipuler des fichiers SSA/ASS.
- libccss-1-5 : Bibliothèque permettant de manipuler des fichiers CSS.
- mail
- dma : MTA léger destiné pour un usage personnel et/ou superficiel. Il gère aussi bien les MUA locaux que des serveurs SMTP distant via TLS/SSL et authentification SMTP.
- icedove-attachmentreminder : Cette extension est très pratique si comme moi vous oubliez tout le temps d'ajouter la pièce jointe que vous êtes censés envoyer avec le mail que vous être en train d'écrire exprès pour ça. Un algorithme détecte si l'on fait référence à une pièce jointe dans le corps du mail et nous affiche une fenêtre popup si jamais on n'a pas mis de pièce jointe. Ce qui veut dire que si vous n'écrivez rien lorsque que vous devez juste envoyer la pièce jointe… Cette extension ne vous sera en fait pas d'une grande aide.
- icedove-gcontactsync : Je ne suis personnellement pas fan de gmail. Mais bon, comme je sais que tout le monde n'est pas parfait, j'ai pitié de vous et vous en fait profiter.
- schleuder : Gestionnaire de listes de discussions passant par GPG et assurant ainsi des discussions chiffrées et pseudo-anonymes.
- math
- gfm : Logiciel permettant de manipuler des fichiers dans le format utilisé sur les calculatrices Texas Instruments.
- tilp2 : Logiciel permettant le transfert de données entre votre ordinateur et votre Texas Instruments. Il gère les différents types de cable (gris, noir, silver et direct), faire des copies d'écran, installer des « applications FLASH », mettre à jour l'« OS », etc.
- misc
- pslist : Permet de lister tous les processus descendants d'un processus. Il permet aussi de faire un kill récursif avec la commande rkill, ainsi que changer la priorité récursivement.
- thinkfan : Permet de contrôler plus finement la vitesse des ventilateurs quand le matériel ne le gère pas très bien.
- weirdx : Il aurait fallu offrir une SuSE et une corde à ces gens là. Ça leur aurait évité de nous pondre un serveur X en java…
- net
- minbif : Clone de bitlbee, mais reposant sur l'utilisation de libpurple.
- prosody : Serveur XMPP en lua. Très jeune et très prometteur, il est pourtant déjà fort intéressant. De plus l'équipe de développement est très active et réactive. Il bat déjà jabberd14 sur bien des points (notamment parce qu'il gère PEP). À noter qu'il n'utilise aucun SGBD, en effet il stocke tout sur le système de fichiers. Et ça, ça rox.
- proxytunnel : Permet de créer des tunnels tcp passant par des proxys HTTPS pour être utilisés via ssh. Il connecte stdin et stdout à un serveur en passant par un proxy HTTPS. Il a été conçu à l'origine pour être utilisé comme une extension à SSH mais peut-être utilisé avec d'autres applications.
- shorewall : Vous ne verrez plus jamais iptables comme avant. Il s'agit en fait de la fusion de shorewall-common, shorewall-shell et shorewall-perl.
- stone : Répéteur de paquets TCP et UDP devant passer au travers d'un firewall (en entrée ou en sortie).
- transmission-qt : Interface graphique en Qt pour transmission.
- otherosfs
- makefs : Outil permettant de générer une image iso à partir d'une hierarchie de répertoires et de fichiers.
- python
- pymetrics : Outils d'analyse de code python. Je n'ai toutefois pas très bien compris la logique du bousin.
- python-aafigure : Utilisable en ligne de commande ou via un module python, python-aafigure permet de générer une image (entre autres au format SVG, PNG et PDF) à partir d'un ASCII art.
- python-argparse : Clone de optparse se voulant plus fonctionnel que lui. Comme par exemple la gestion d'arguments positionnels, plus d'aide et de messages d'usage et la possibilité de créer des parseurs pour des sous-commandes.
- python-daemon : Créer un démon en python n'aura jamais été aussi simple que d'utiliser un module. Ce module permet en effet de faire en sorte que son programme se comporte comme un vrai démon, comme spécifié dans la PEP-3143.
- python-evince : Module permettant d'afficher des documents pdf en utilisant libevince.
- python-fstab : Module permettant de manipuler de manière « transparente » le fichier /etc/fstab. Par exemple, on peut lire le fichier, changer le point de montage d'un des systèmes de fichiers et écrire le résultat. Et le module s'arrangera pour qu'il n'y ait que le point de montage qui soit modifié (en d'autres termes, il s'arrange pour ne pas modifier le reste du fichier qui n'a pas besoin de l'être, donc il ne touchera pas aux indentations, espaces et autres).
- python-inotifyx : Concurent direct à pyinotifyx. Il a comme particularité d'être écrit quasiment entièrement en C et de ne pas utiliser les ctypes. Ce qui le rend donc plus rapide. Il est aussi plus proche de inotify et plus simple que ne l'est pyinotify. Cependant il gère moins de fonctionnalités (par contre il paraît qu'elles ne sont pas très utiles celles qui manquent). Il semblerait aussi qu'il ait une API plus stable que cette de pyinotify qui semble changer plutôt souvent et sans avoir forcément de raison valable.
- python-instant : Module permettant d'utiliser du code C dans du code python. Dans l'exemple de base visible sur le site officiel, l'auteur du projet nous annonce un gain de temps assez intéressant. Toutefois, on est en droit de s'interroger sur la réelle utilité d'un tel projet. Malgré cela, ce module peut s'avérer fort pratique si l'on est parti pour coder un module en C. Cela pourrait éventuellement d'avoir à le faire si le bout de code n'est pas trop complexe.
- python-keybinder : Module permettant à une application d'enregistrer des raccourcis claviers GTK.
- python-lamson : Pur serveur STMP écrit en python.
- python-mock : Permet de créer des objets mock dans le cadre de tests unitaires. Un objet mock est un objet controllé qui simule le comportement d'un autre. On peut par exemple connaître l'ensemble des méthodes appelés avec la liste des arguments à chaque fois. On peut aussi donner un jeu de valeur à retourner pour telle ou telle méthode. C'est un concept très intéressant et surtout fort pratique. Pour certains bouts de code, écrire un test unitaire se révèle être un vrai casse-tête. python-mock permettra donc de s'éviter bien des migraines.
- python-pyosd : Module permettant d'ajouter un OSD à vos applications.
- python-sponge : Framework web basé sur CherryPy et Genshi qui suit le concept DRY.
- shells
- lshell : Shell codé en python permettant de restreindre l'accès à certaines commandes, d'activer ou de désactiver certaines commandes via SSH, d'enregistrer les commandes de l'utilisateur, d'avoir des restrictions liées au temps, etc.
- sound
- taggrepper : Clone de grep spécialisé dans la recherche parmis les tags de fichiers MP3, Ogg Vorbis et FLAC en utilisant une expression régulière.
- tex
- latexdiff : Permet de faire un diff entre deux fichiers latex. Cette commande se veut plus adaptée qu'un « vulgaire » diff. Elle génère un nouveau fichier latex avec les différences annotées.
- text
- apvlv : Visualisateur de fichiers PDF se manipulant comme vim. « :o foo » permet par exemple d'ouvrir le fichier « foo ». À noter qu'avec emacs23, on peut directement visualiser les PDF sans passer par un programme tiers.
- pdfchain : Outil permettant de manipuler des fichiers PDF. Grâce à lui on peut fusionner des fichiers, les découper, ajouter des arrières plans, etc.
- pdfresurrect : Outil permettant de manipuler l'historique contenu dans un fichier PDF.
- utils
- agedu : Après du et ncdu, voici un autre utilitaire dont vous ne pourrez plus vous passer. Plutôt que de se contenter de vous afficher uniquement la taille qu'occupent les fichiers de vos répertoires, il indique en plus la date de dernier accès des fichiers. Il part en effet du principe qu'afficher bêtement l'espace occupé n'est pas pertinent car parfois on a vraiment besoin de cet espace. Par contre, une archive qu'on a décompressé et dont on a totalement oublié l'existence sera mis en évidence par ce système. Comme du et ncdu, il nécessite de construire un index des fichiers du répertoire que l'on veut traiter. À la différence près qu'il doit la stocker sur le système de fichier, et qu'il travaillera par la suite dessus. La mise à jour n'est donc pas automatique… Pour se faire, il faut taper « agedu -s . ». Ensuite pour analyser le résultat, je suis passé par le serveur web embarqué que l'on lance avec « agedu -w ». En se rendant à l'adresse qu'il nous indique, on tombe devant un résultat qui n'est pas sans nous rappeler celui de ncdu, mais en version web. Toutefois une différence de taille fait son apparition : La barre d'occupation de l'espace disque est colorée. Plus on tend vers le rouge et plus les fichiers sont vieux. On peut donc ainsi facilement repérer les répertoires qui contiennent le plus de fichiers que l'on n'utilise quasiment jamais, voire pas du tout. J'ai par exemple sur mes disques des fichiers auquel je n'ai pas touché depuis plus de 2ans…
- debtree : Outil permettant de générer un graphique mettant en évidence la relation entre des paquets debian.
- go2 : Permet d'augmenter la vitesse à laquelle on se déplace dans le système de fichiers en proposant une manière plus rapide pour indiquer le répertoire que l'on cherche a atteindre. À noter qu'il existe une interface graphique en GTK que l'on obtient en rajoutant « --gui » sur la ligne de commande. À noter que le mainteneur a fait du grand n'importe quoi. Ainsi, il m'a fallu taper « /usr/lib/go2/go2.py » pour lancer l'application car elle n'est pas dans le PATH. « /usr/share/doc/go2/README.Debian » nous apprend qu'il faut placer une ligne « obscure » dans notre ~/.bashrc pour pouvoir l'utiliser en tapant seulement « go2 ». Je trouve cela vraiment stupide. De plus, bien que l'application dépende de GTK pour l'interface graphique, il n'en est fait nul mention dans les dépendances du paquet. Heureusement, il y a déjà un rapport de bug pour ça.
- luckybackup : Interface graphique pour gérer la sauvegarde de données en passant par rsync.
- mdm : Outil permettant de paralléliser ses scripts shell.
- lxshortcut : Petit programme graphique pour lxde permettant de personnaliser les .desktop et de mettre des raccourcis vers des applications sur le bureau.
- vcs
- easygit : Git pour les simples mortels. Il s'agit d'une surcouche à git ayant pour but de simplifier son utilisation pour les utilisateurs moins avancés.
- gitstats : Générateur de statistiques pour dépôts git.
- mercurial-git : Permet d'interagir avec un dépôt git en passant par mercurial.
- video
- kplayer : Lecteur multimedia pour KDE basé sur mplayer.
- web
- iceweasel-downloadstatusbar : Extension permettant de gérer les téléchargements depuis la barre de statut plutôt que de passer par la fenêtre dédiée qui nous gène dans notre navigation.
- iceweasel-fission : Extension permettant de fusionner la barre d'adresse et la barre de recherche.
- kpart-webkit : Greffon pour KDE permettant d'utiliser Webkit à la place de KHTML.
- mozilla-pwdhash : Extension pour iceweasel permettant de générer à la volé un mot de passe unique pour chaque site en se basant sur celui tapé par l'utilisateur. Entre autres avantages, bien qu'il ne chiffre pas les mots de passe, il rend leur cassage par dictionnaire bien plus compliqué que le mot de passe tapé par l'utilisateur. De plus si quelqu'un s'empare d'un hash et qu'il arrive à retrouver le mot de passe associé, il ne pourra s'en servir que pour le site auquel il est dédié.
- uzbl : Navigateur ultra minimaliste disposant d'un système de greffons pour l'étendre.
- zine : Logiciel développé en python à la wordpress et dotclear pour faire un blog.
- x11
- e17 : Enlightenment DR17 est enfin entré dans sid.
- lxinput : Permet de configurer le clavier et la souris sous lxde.
- lxsession : Gestionnaire de session pour lxde.
- mutter : Gestionnaire de fenêtres basé sur clutter.
- slim : Ce paquet est nouveau sans vraiment l'être. Il a en fait quitté les dépôts pendant quelques jours. La cause principal de cet abandon était que le paquet n'était plus maintenu en upstream, ce qui n'est plus le cas. Le paquet nous revient donc, avec un nouveau mainteneur en prime. Pour ceux qui ne connaissent pas, il s'agit d'un gestionnaire de connexion graphique très léger.
- wbar : Barre de lancement rapide initialement développée pour Fluxbox, mais qui fonctionne avec n'importe quel gestionnaire de fenêtres.
- xfce
- xfce4-clipman : Permet une gestion avancée des sélections faites par X.
- admin






