Python
Monday, 28 September 2015
|
Écrit par
Grégory Soutadé

Capture d'écran Dénote

Après le blog, on est à la limite du tutorial de base Django : une application de gestion de notes. D'ailleurs, un blog et un gestionnaire de note sont très proches au niveau structure du code et fonctionnalités.

Pourtant, c'est une application qui me manquait cruellement : Écrire des petites notes, pouvoir les stocker/organiser et y accéder de partout. Je n'ai pas trouvé ailleurs sur le web une appli open source en Python/PHP facilement installable chez soi.

Pourquoi ne pas utiliser le téléphone me direz-vous ? Et bien, quand on veut juste copier-coller un lien d'Internet, ajouter deux/trois commentaires pour y retourner plus tard, c'est bien plus pratique de le faire sur son PC. Je n'ai pas non plus envie d'être restreint aux seuls marque-pages.

Qu'en est-il de pastebin ? Je vous avais vanté les mérites de ce petit logiciel de copier-coller communautaire. Il faut reconnaître qu'il est bien pratique pour s'échanger des bouts de code (ou autre) pendant une courte durée. Mais, dès qu'ils s'agit de garder et d'organiser ses "pastes", et bien on atteint très vite ses limites.

Voilà donc "Dénote" en version 0.1. Ses fonctionnalités sont :

  • Ajout/suppression de note
  • Syntaxe markdown (avec support de la coloration de code)
  • Catégories

Que du très classique, avec un design simple, mais qui colle assez bien à l'application (de mon point de vue). J'ai eu la joie de réaliser tout le design (c'est quand même mieux que gPass), et, pour être honnête, je le trouve plutôt sympa.

Comme d'habitude les sources sont disponibles sur ma forge sous licence GPLv3. Il existe une instance ouverte (soumise à création de compte (un minimum d'info est demandé)) est disponible ici, c'est celle que j'utilise.

De mon point de vue, il manque encore la recherche ainsi que (éventuellement) un système de note publique/privée (actuellement tout est privé).

À défaut d'être révolutionnaire, cette petite m'a permis de remonter les soucis de conflit lorsque l'on fait tourner deux applications Django dans une même instance Apache.

Thursday, 16 July 2015
|
Écrit par
Grégory Soutadé

Capture d'écran IWLA

Deuxième version d'IWLA, le clone d'AWSTATSl'analyseur de log web écrit en Python.

Qu'est ce qu'on trouve dans cette version ? Et bien ... tout. Cette version arrive au niveau d'AWSTATS en ce qui concerne mon usage, et même le dépasse !

Quelques fonctions non présentes dans AWSTATS :

  • (Meilleure) Détection des robots
  • Affichage des différences entre deux analyses
  • Ajout facile des ses propres moteurs de recherche
  • Traçage d'IP
  • Détection de lecteur de flux RSS
  • Support des fichiers de log compressés

Pour le reste, on retrouve toutes les briques de bases. Mon seul regret est de n'avoir pas encore mis en place les tests automatiques.

Tuesday, 23 December 2014
|
Écrit par
Grégory Soutadé

Capture d'écran IWLA

C'est mon cadeau de noël à moi : IWLA. Il s'agit, basiquement, d'un clone d'AWSTATS. Pour ceux qui ne connaissent pas, awstats est un analyseur de log (journal des entrées) d'un serveur web (ce dernier faisant aussi l'analyse des logs ftp, ssh, mail...).

C'est un projet qui me tenait à cœur depuis longtemps et, mine de rien, il y a pas mal de boulot juste pour faire des additions !

IWLA a été pensé pour être le plus modulaire possible. Contrairement à awstats qui est complètement monolithique (tout le code dans gros un fichier PERL), l'extraction des statistiques et l'affichage de celles-ci passe par des plugins (hormis les opérations de base). On peut donc ajouter/retirer/modifier à loisir des modules et obtenir exactement ce que l'on veut (et ce de manière très simple). Chaque module va s'occuper de sa partie, voire modifier le résultat des modules précédents !

L'autre avantage (ou inconvénient), est qu'IWLA génère uniquement des pages statiques (en plus de pouvoir les compresser), ce qui accélère la visualisation. Côté design, il reprend le thème d'awstats (ça aurait été beaucoup plus moche si je l'avais fait moi-même) : un design simple qui va à l'essentiel !

Mais ce n'est pas tout, les données (robots, moteurs de recherche), sont directement extraites d'awstats !

Pour finir de troller, IWLA est écrit en Python, ce qui est bien plus moderne :)

Le tout est disponible sous licence GPL sur ma forge. Amusez-vous bien !

Monday, 22 October 2012
|
Écrit par
Grégory Soutadé

Working with OpenOffice/LibreOffice Spreadsheets with Python One improvement of OpenOffice was to introduce Python scripting beside VBA one. You can do internal or external scripting. External scripting is done via Python UNO interface, it's like CORBA objects (...). But resources on web are poor and sparse. Only two websites have a clear and complete information :
https://www.wzdftpd.net/downloads/oowall/pyUnoServerV2.py
http://stuvel.eu/ooo-python

This is a mini HOWTO you can use in your external scripts First you have to start server side OOo/LO :

libreoffice "--accept=socket,host=localhost,port=2002;urp;" --invisible

If you don't want to see OOo/LO interface, add --headless. WARNING: You need to close ALL OOo/LO instances before starting server !

Next, load a document :

def connect(port, filename): # get the uno component context from the PyUNO runtime localContext = uno.getComponentContext() # create the UnoUrlResolver resolver = localContext.ServiceManager.createInstanceWithContext( "com.sun.star.bridge.UnoUrlResolver", localContext) # connect to the running office ctx = resolver.resolve("uno:socket,host=localhost,port=" + str(port) + ";urp;StarOffice.ComponentContext") smgr = ctx.ServiceManager # get the central desktop object DESKTOP =smgr.createInstanceWithContext("com.sun.star.frame.Desktop", ctx) url = unohelper.systemPathToFileUrl( os.path.abspath(filename)) doc = DESKTOP.loadComponentFromURL(url, '_blank', 0, ()) return doc

You can get sheets inside document by creating an enumeration :

doc = connect(port, filename) sheets = doc.getSheets() sheet_enum = sheets.createEnumeration() while sheet_enum.hasMoreElements(): sheet = sheet_enum.nextElement() print sheet.getName()

Retrieve cells :

cell = sheet.getCellByPosition(col, row)

You can use following methods on cell objects : XCell

To retrieve cell type (CellContentType) :

cell.getType()

For me object (or enumeration) comparison fails, so I use string comparison :

if cell.getType().value != 'EMPTY':

cell.getValue() will return cell float value (0.0 if cell is empty or text). Most of the case you need to cast it into int value : int(cell.getValue()) or do all your code with float values !!

Be careful, sometimes cells values are formated with text but contains float/integer !! value = value_cell.getString() will return "0x45"

Now you have all basics to do a spreadsheet parser ! If you don't know how to handle an object, juste print it and look at its supportedInterfaces dictionary, OOo API doc will tells how to handle them.

Wednesday, 22 August 2012
|
Écrit par
Grégory Soutadé

For the dynastie project, I need to load data encoded in UTF-8 with Python minidom XML parser. But when I wrote node.toxml('utf-8') to display the XML tree, I get this error :

UnicodeDecodeError at /generate/1

'ascii' codec can't decode byte 0xc2 in position 187: ordinal not in range(128)

In facts Python thinks that all data in XML tree are in ASCII and try to encode it into UTF-8 (or anything else you supplied). The solution is to use your own writer that will convert all non utf-8 strings in unicode string which can be then re-encoded in every format (like utf-8). This doesn't appears in Python 3 because, in Python 3, all strings are already in unicode. Add the following class to your code :

class UnicodeWriter(codecs.StreamWriter): encode = codecs.utf_8_encode def __init__(self): self.value = u'' def write(self, object): if not type(object) == unicode: self.value = self.value + unicode(object, 'utf-8') else: self.value = self.value + object return self.value def reset(self): self.value = u'' def getvalue(self): return self.value

And our node.toxml('utf-8') becomes :

writer = UnicodeWriter() node.writexml(writer) writer.getvalue().encode('utf-8')