Question de conception, GSPanel

La réalisation de GSPanel avance tranquillement, et je bloque actuellement sur un point, donc j'aimerai votre avis.

Lorsqu'un utilisateur aura ajouté une machine, il devra ajouter des jeux. Au niveau structurel, la page d'ajout proposera au tout début une simple liste déroulante, contenant tous les jeux proposés. Une fois que l'utilisateur aura fait son choix, le vrai formulaire apparaîtra avec les valeurs adéquates (nom du jeu, version, dossier d'installation, etc).

Le problème est au niveau des jeux. A la base, je pensais que le mieux était de faire un fichier xml par jeux. Ce fichier contiendrait les informations suivantes :

  • Nom (du jeu)
  • Version
  • Logo
  • Chemin du script d'installation (sur nos serevurs)
  • Liste de paramètres pour le script
  • Chemin d'exécution du jeu
  • Paramètres pour lancer le jeu (tel que port, ip, etc)

(d'ailleurs, si j'en oublie, n'hésitez pas !)

Le problème, est que pour afficher une liste de 50 jeux, il faudra parcourir 50 fichiers, et en plus ouvrir celui que l'utilisateur aura sélectionné pour récupérer les autres données, et cela à chaque fois que l'utilisateur affichera la page "Ajouter".

Ça peux vite devenir lourd !

Du coup, j'aurais deux solutions, mais j'aimerai vos avis (quelle solution serait la meilleure ? (d'autres propositions sont permises)) :

  1. Faire un master file xml, qui contiendrait la liste des fichiers xml avec le nom du jeu (la liste affichera le nom et aura comme clée le fichier).
    Le problème avec cette méthode est qu'il faut mettre à jour le master file à chaque fois qu'un nouveau jeu est ajouté.
  2. L'autre solution consisterait à tout mettre en base. On oublie complètement le chargement des fichiers xml dans ce cas. Là, le problème est que cette implémentation impose la création de trois nouvelles tables : les informations du jeu, les paramètres du script d'installation et les paramètres du jeu.

D'après vous, quelle serait la meilleure méthode, laquelle utiliseriez-vous ? Serait-ce la 1 ? la 2 ? ou une autre carrément plus adaptée ? :)

Merci de me laisser vos avis !

Filed under  //  Development   GSPanel   Projects   Python   avis   base   installation   jeu   liste   paramètres   question   script   table   xml  
Posted by Cyril Nicodème 

Netbeans : Only using space tabs for python

I like to use tab as separator for all my files (html/css/js) but it is recommended to use space tabulation for python files.

With netbeans, the problem is if you go in the preferences :

Tools > Options > Editor > Formatting

you can see the parameter "Expand tabs to spaces" when you are using "Language : All Languages" and "Category : Tabs and Indents" (Of course, I didn't checked this one in order to have tabs and not space).

But, now if you choose Python as Language, there is no "Tabs and Indents" category.

So by default, you had to choose to expand tabs to space for all your files in order to have the python files to work.

But I've found the solution to just using space for python files, and tab for the rest.

All you have to do is to add the following lines to the file

[Netbeans Installed Folder]/.netbeans/6.8/config/Editors/text/x-python/Preferences/org-netbeans-modules-editor-settings-CustomPreferences.xml
<entry javaType="java.lang.String" name="code-template-expand-key" xml:space="preserve">
        <value><![CDATA[TAB]]></value>
    </entry>
    <entry javaType="java.lang.Boolean" name="expand-tabs" xml:space="preserve">
        <value><![CDATA[true]]></value>
    </entry>

Restart your editors and that's it ! You can now have space for python and tabs for the rest of your script files !

Hope this helps !

Filed under  //  Development   Netbeans 6.8   Projects   Python   expand   indent   size   space   tabs  
Posted by Cyril Nicodème 

Django en serveur - Sommaire : Site en Python (Django) chez OVH

(Voici la suite de ma petite série “faire mumuse avec python sur son serveur”.)

Nous avons vu précédemment comment configurer notre projet Django pour qu'il fonctionne sur un serveur Apache, en utilisant soit mod_python, soit mod_wsgi. Comme j'ai réalisé ce projet pour un client, je lui ai pris avec un forfait Start1G chez OVH.

Ce serait bête de ne pas l'utiliser ! :)

J'ai donc fait quelques recherches sur le web sur comment faire fonctionner un projet python sur un hébergeur qui, à la base, n'accepte que du Php. Heureusement pour moi, j'ai trouvé deux articles complémentaires qui m'ont permis de faire fonctionner mon site :

Le premier article est très complet et c'est parce que j'ai eu quelques difficultés à y arriver que je poste ma solution, sinon j'aurais juste mis le liens vers ce site. Le second peux donner quelques idées pour résoudre vos soucis, mais les liens vers les documents (.htaccess, django.cgi) retournent des erreurs 404.

Alors voilà, comme toujours, il faut respecter une certaine arborescence, qui dépends de vos goûts je doit dire.

Pour ma part, voici l'arborescence finale :

  • cgi-bin/ : dossier par défaut fournis par OVH, non modifié
  • projet/
  • [project_name]/ : le nom du projet, contient le code python, dont le settings.py
  • static/ : les fichiers statiques (css, js, images, etc)
  • templates/ : les templates nécessaires à l'affichage du site.
  • python-local/ : contient tout ce qui est nécessaire au fonctionnement du site, dans mon cas, juste Django
  • django/ : le framework Django
  • requetes/ : dossier par défaut fournis par OVH, non modifié
  • www/
  • media/ : copie du repertoire django/django/contrib/admin/media/ (medias utilisés par l'admin)
  • .htaccess
  • django.cgi

Voici le contenu des fichiers .htaccess et django.cgi

.htaccess : très simple, mais efficace ;)

RewriteEngine on
RewriteBase /
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.*)$ django.cgi/$1 [L]

django.cgi.
Vous pourrez trouver une version originale de ce fichier ici.

#!/usr/bin/env python
# encoding: utf-8
"""
django.cgi

A simple cgi script which uses the django WSGI to serve requests.

Code copy/pasted from PEP-0333 and then tweaked to serve django.
http://www.python.org/dev/peps/pep-0333/#the-server-gateway-side

This script assumes django is on your sys.path, and that your site code is at
/home/mycode/mysite. Copy this script into your cgi-bin directory (or do
whatever you need to to make a cgi script executable on your system), and then
update the paths at the bottom of this file to suit your site.

This is probably the slowest way to serve django pages, as the python
interpreter, the django code-base and your site code has to be loaded every
time a request is served. FCGI and mod_python solve this problem, use them if
you can.

In order to speed things up it may be worth experimenting with running
uncompressed zips on the sys.path for django and the site code, as this can be
(theorectically) faster. See PEP-0273 (specifically Benchmarks).
http://www.python.org/dev/peps/pep-0273/

Make sure all python files are compiled in your code base. See
http://docs.python.org/lib/module-compileall.html

"""

import os, sys

sys.path.append("/[racine]/python-local/django")
sys.path.append("/[racine]/[projet]")

import django.core.handlers.wsgi

def run_with_cgi(application):

    environ                      = dict(os.environ.items())
    environ['wsgi.input']        = sys.stdin
    environ['wsgi.errors']       = sys.stderr
    environ['wsgi.version']      = (1,0)
    environ['wsgi.multithread']  = False
    environ['wsgi.multiprocess'] = True
    environ['wsgi.run_once']     = True

    if environ.get('HTTPS','off') in ('on','1'):
        environ['wsgi.url_scheme'] = 'https'
    else:
        environ['wsgi.url_scheme'] = 'http'

    headers_set  = []
    headers_sent = []

    def write(data):
        if not headers_set:
             raise AssertionError("write() before start_response()")

        elif not headers_sent:
             # Before the first output, send the stored headers
             status, response_headers = headers_sent[:] = headers_set
             sys.stdout.write('Status: %s\r\n' % status)
             for header in response_headers:
                 sys.stdout.write('%s: %s\r\n' % header)
             sys.stdout.write('\r\n')

        sys.stdout.write(data)
        sys.stdout.flush()

    def start_response(status,response_headers,exc_info=None):
        if exc_info:
            try:
                if headers_sent:
                    # Re-raise original exception if headers sent
                    raise exc_info[0], exc_info[1], exc_info[2]
            finally:
                exc_info = None     # avoid dangling circular ref
        elif headers_set:
            raise AssertionError("Headers already set!")

        headers_set[:] = [status,response_headers]
        return write

    result = application(environ, start_response)
    try:
        for data in result:
            if data:    # don't send headers until body appears
                write(data)
        if not headers_sent:
            write('')   # send headers now if body was empty
    finally:
        if hasattr(result,'close'):
            result.close()

# Change mysite to the name of your site package
os.environ['DJANGO_SETTINGS_MODULE'] = '[projet].settings'

run_with_cgi(django.core.handlers.wsgi.WSGIHandler())

Bien évidement, vous modifierez les valeurs de [racine] et de [projet] par celle correspondantes.

Pour évaluer [racine], j'ai fait un simple script php qui me faisait un echo de $_SERVER["DOCUMENT_ROOT"] :

<?php
echo $_SERVER["DOCUMENT_ROOT"];
?>

Pour [projet], c'est le nom que vous avez donné à votre projet python.

Enfin, n'oubliez pas d'adapter les chemins dans votre fichier settings.py à votre structure.

Normalement, si vous tentez d'accéder à votre site maintenant, vous aurez une erreur 500. Si vous regardez les logs d'erreurs, voici le type d'erreur que vous aurez :

Premature end of script headers: django.cgi suexec policy violation: see suexec log for more details

En fait, l'erreur est très conne ici. Tout ce que vous avez à faire, c'est donner les bons droits à votre fichier django.cgi, notamment le fait qu'il soit exécutable.

Pour ma part, seul le droit -rwx------ (tous les droits pour l'utilisateur, et rien pour le groupe et les autres) fonctionne. A vous de voir.

Maintenant, un petit F5 sur votre site et il devrait-être opérationnel !

Voilà ! C'est la fin de ma petite série sur Django, j'espère que vous avez apprécié :) Si vous avez des questions n'hésitez pas, les commentaires sont fait pour ça !

Pour ma part, j'aurai préféré avoir un raccourcis de media dans www qui pointe sur le dossier django/contrib/admin/media, mais je n'ai pas trouvé comment faire cela dans FileZilla. Si c'est possible et que vous savez comment faire, je suis impatient d'avoir votre explication :)

Filed under  //  Development   Projects   Python   django   media   ovh   site  
Posted by Cyril Nicodème 

Django en serveur - Sommaire : Site en Python (Django) sous Apache avec mod_wsgi.

(Voici la suite de ma petite série "faire mumuse avec python sur son serveur".)

Nous venons de voir la mise en ligne de notre projet développé en python en utilisant mod_python.

Mais aujourd'hui, nous pouvons utiliser un nouveau module, plus performant que ce dernier, alors pourquoi s'en priver ?

Tout d'abord, installons le. Sous Debian, voici la commande :

apt-get install libapache2-mod-wsgi

Puis activons le :

a2enmod wsgi

ou à la mano :

ln -s /etc/apache2/mods-available/wsgi.load /etc/apache2/mods-enabled/
ln -s /etc/apache2/mods-available/wsgi.conf /etc/apache2/mods-enabled/

Remarquez qu'il y a aussi un fichier de configuration !
(par défaut, ce fichier de configuration est entièrement commenté. Vous pouvez donc l'ignorer.)

Maintenant, passons aux choses sérieuses, voici à quoi ressemblera votre VirtualHost :

<VirtualHost *:80>
        ServerAdmin postmaster@[domain].tld
        ServerName www.[domain].tld
        ServerAlias [domain].tld
        DocumentRoot /var/www/[domain]/www/[domain]
 
        ErrorLog /var/log/apache2/[domain]_error.log
        LogLevel warn
        CustomLog /var/log/apache2/[domain]_access.log combined
        ServerSignature Off
 
        WSGIScriptAlias / /var/www/[domain]/www/[project_name]/django.wsgi
 
        Alias /media "/var/www/[domain]/www/media"
        <Location "/media/">
                SetHandler None
        </Location>
 
        Alias /static "/var/www/[domain]/www/static"
        <Location "/static/">
                SetHandler None
        </Location>
 
        <LocationMatch "\.(jpg|gif|png)$">
                SetHandler None
        </LocationMatch>
</VirtualHost>

Je passerai sur l'explication des directives pour media et static, que vous trouverez sur le précédent article.

La ligne qui nous intéressent vraiment ici, c'est :
WSGIScriptAlias / /var/www/[domain]/www/[domain]/django.wsgi.

Comme nous l'avions vu dans le précédent article, ma structure de dossier est faite de telle manière que j'ai un dossier correspondant au sous domaine (ici, www), et dedans, trois dossiers :
domain (le même nom que le domaine (aka le nom du projet), qui contiens le code python,
static et
templates).

Maintenant, voici le contenu du fichier django.wsgi :

import os
import sys

sys.path.append('/var/www/[domain]/www/')

os.environ['DJANGO_SETTINGS_MODULE'] = 'domain.settings'

import django.core.handlers.wsgi
application = django.core.handlers.wsgi.WSGIHandler()

Remarquez que j'ajoute le projet au python path (avec la ligne "sys.path.append"). Je ne précise pas le répertoire qui contiens le code, car la ligne d'après s'en charge (de "/var/www/[domain]/www/" à "domain.settings", j'obtiens /var/www/[domain]/www/[domain]/settings.py !

Redémarrez Apache et voilà !

Tout fonctionne !

Bon, la première fois, ça peut-être un peu long à charger, mais ensuite, le site sera fluide et agréable à naviguer !

Si vous avez des problèmes avec le thème de la partie Admin, vous avez oublié de faire un lien symbolique vers le répertoire "media" du module admin de Django. Pour avoir la démarche, c'est ici.

De plus, si vous désirez plus de détails concernant le module Wsgi, cette page vous aidera probablement.

Filed under  //  Apache   Development   Projects   Python   django   mod   mod_wsgi   wsgi  
Posted by Cyril Nicodème 

Django en serveur - Sommaire : Site en Python (Django) sous Apache avec mod_python.

(Voici la suite de ma petite série "faire mumuse avec python sur son serveur".)

Lorsque j'ai parlé du framework python Django, beaucoup d'entre vous m'ont fait la réfléxion du :

Ça à l'air cool (ça l'est ! :p), mais la dernière fois que j'ai tenté de faire marcher python avec apache, ça a été l'enfer !

Ce jour est révolu :) Bon, sur le site de Django, ils conseillent d'utiliser mod_wsgi, mais pour ce tutoriel, nous utiliserons mod_python.

Donc tout d'abord, nous allons l'installer (méthode pour Debian) :

apt-get install libapache2-mod-python

Ensuite, il va falloir l'activer :

a2enmod python

ou équivalent :

ln -s /etc/apache2/mods-available/python.load /etc/apache2/mods-enabled/

Ensuite, il va falloir créer un VirtualHost qui indiquera à Apache que pour ce domaine, il faut utiliser python. Voici un exemple de VirtualHost spécifique à Django :

<VirtualHost *:80>
        ServerAdmin postmaster@[domain].tld
        ServerName www.[domain].tld
        ServerAlias [domain].tld
        DocumentRoot /var/www/[domain]/www/[domain]

        ErrorLog /var/log/apache2/[domain]_error.log
        LogLevel warn
        CustomLog /var/log/apache2/[domain]_access.log combined
        ServerSignature Off

        <Location "/">
                SetHandler mod_python
                PythonHandler django.core.handlers.modpython
                SetEnv DJANGO_SETTINGS_MODULE [nom_du_projet_django].settings
                PythonPath "['/var/www/[domain]/www/'] + sys.path"
                PythonAutoReload Off
                PythonDebug Off
        </Location>
 
        Alias /media "/var/www/[domain]/www/media"
        <Location "/media/">
                SetHandler None
        </Location>
 
        Alias /static "/var/www/[domain]/www/static"
        <Location "/static/">
                SetHandler None
        </Location>
 
        <LocationMatch "\.(jpg|gif|png)$">
                SetHandler None
        </LocationMatch>
</VirtualHost>

Quelques explications s'imposent. Pour mes projets Django, j'ai choisis de faire un structure simple. Dans le dossier de mon projet (appelons le "domain"), j'ai le nom du sous-domaine (ici, www), et dedans, je crée trois dossiers :

  • [domain] (le même nom que son dossier parent aka le nom du projet) : il contiendra le code Django
  • static : il contiendra tous les fichiers nécéssaire au site : css, js, images, etc
  • template : il contient les templates utilisés par Django

Du coup, le fichier de configuration semble un peu plus clair : on définis un Handler de type python pour le répertoire qui contient le code python (/var/www/[domain]/www/[domain]), puis on définis un Handler null (donc aucune interprétation d'un quelconque code) pour les autres dossiers (media et static).

Maintenant, vous vous demandez à quoi sert "media".

En fait, ce répertoire est un liens symbolique que nous allons créer, et qui pointe sur le module admin de Django. En effet, dans la configuration actuelle, si vous tentez d'accéder à l'admin (en ajoutant un /admin/ sur l'url), vous verrez que les images, le style et le javascript ne sont pas présents.

Logique ! Comment apache peux deviner d'où ils viennent ?

Donc pour que notre admin soit fonctionnel, il faut faire un lien symbolique du module admin à notre projet (en supposant que vous avez installez Django comme indiquez dans notre précédent article) :

ln -s /opt/django/django/contrib/admin/media/ /var/www/[domain]/www/media

Du coup, la configuration dans votre VirtualHost prendra aussi effet pour ce répertoire.

Voilà !

Vous n'avez plus qu'à redémarrer, et si votre fichier settings.py de votre projet est correct (notamment au niveau des répertoires ;)), votre site devrait-être accessible !

Filed under  //  Apache   Development   Projects   Python   django   media   mod-python   server   static   template  
Posted by Cyril Nicodème 

Django en serveur - Sommaire : Installer la version trunk de Django sur son serveur.

(Note: pour cet article, nous supposerons que vous avez déjà python et subversion d'installé (et accessoirement MySQL).)

Dans ma série de "faire mumuse avec python sur son serveur web", voici le premier épisode :

Installer Django (le framework Python) en version en développement sur sa machine.

Pour ce faire, c'est très simple.
D'ailleurs, le site officiel de django l'explique de manière très détaillée.

Tout d'abord, rendez-vous dans le répertoire ou vous déposerez la version en développement de Django.

Pour ma part, je l'ai mis dant /opt.

cd /opt

Ensuite, récupérez Django avec subversion :

svn co http://code.djangoproject.com/svn/django/trunk/ django-trunk

Une fois la récupération terminée, vous devrez lier django dans les packages de python. Afin de connaître le chemin exact vers le site-packages de python, executez cette commande :

python -c "from distutils.sysconfig import get_python_lib; print get_python_lib()"

Vous n'aurez plus ensuite qu'à faire un liens symbolique dans le site-packages depuis Django :

ln -s /opt/django-trunk/django [SITE-PACKAGES-DIR]/django

(pensez bien à remplacer la variable [SITE-PACKAGES-DIR] par le résultat de la commande précédente !)

Pour ma part, afin de bien faire fonctionner Django, j'ai du installer quelques modules supplémentaires :

Sous Debian, Vous pourrez récupérer ces deux librairies simplement en faisant un :

apt-get install python-mysqldb et python-imaging

Voilà, Django est prêt à fonctionner !

Filed under  //  Development   Projects   Python   django   server   serveur   subversion   trunk  
Posted by Cyril Nicodème 

Bug de Emesene, libnotify : on_notify_close

Le plugin libNotify de Emesene à un bug gênant, qui génère une erreur (msgbox) indiquant que la fonction on_notify_close n'accepte que deux arguments alors que trois sont donnés :

TypeError?: on_notify_close() takes exactly 2 arguments (3 given)

Pour corriger temporairement ce problème, en attendant une nouvelle version qui corrigera le tout, est de procéder ainsi :

Ouvrez le fichier /usr/share/emesene/plugins_base/LibNotify.py, tout à la fin du fichier, remplacez :

def on_notify_close(self, n):

par

def on_notify_close(self, n, unused):

Voila ! Le bug est parti !!

Bon, cette correction est temporaire et ne corrige pas de manière PROPRE et SURE le problème.

Si vous ne savez pas comment faire ou ce que cela fait, faites attention et/ou attendez la prochaine version de emesene ! :)

Filed under  //  Development   Python   argument   bug   correction   emesene   fix   libnotify   on_notify_close   problem   tree   two  
Posted by Cyril Nicodème