PROJET AUTOBLOG


Sam et Max

source: Sam et Max

⇐ retour index

Internet Explorer 6, 7, 8, 9 Sous Mac/Linux Facilement avec VMWare Fusion

dimanche 18 novembre 2012 à 17:26

Quand on developpe des applications web on doit s’assurer de la compatibilité de ces dernières avec les différents navigateurs du marché. Jusqu’à présent sous MAC/Linux c’était pas évident de tester son application sur Internet Explorer.

J’ai essayé cross-over sous MAC qui ne vaut pas le coup à mes yeux (trop lent, plantage, pas compatible pour certaines versions d’IE, etc.), Wine sous Linux dont cross-over est un dérivé il me semble, mêmes galères.
Il y a aussi IETester qui a l’air pas mal pour avoir toutes les versions d’IE sur un seul navigateur mais il ne marche que sous Windows.

Les choses ont changées et Microsoft propose désormais gratuitement des Images de son Os Windows avec la version IE qui va bien.
La seule contrainte est qu’il faut posséder VMWare (ou VirtualBox GRATUIT), je conseille la version 5 pour 50 euros qui a un mode magique, le mode “Unity” qui fusionne votre Os émulé avec votre Os hôte, j’ai dans mon dock Mac une icône IE8, c’est trop mignon, fluide et pratique.
Une chose non négligeable c’est le copier/coller qui marche entre les deux OS.

Pratique pour voir si son site fonctionne sous IE depuis son Mac


Installation:

Rendez-vous chez Microsoft et téléchargez la version qui vous convient

Une fois les archives téléchargées vous les décompressées (avec The unarchiver sous Mac)

Dans VMWare vous sélectionnez “Ajouter > Importer” et vous importer l’image téléchargée, c’est celle qui comporte l’extension VHD (ex: Win7_IE8.vhd). Il va vous demander de convertir l’image etc, faites mouliner.

Attention:

Le mot de passe des OS est Password1 à taper en clavier QWERTY, si vous n’y arrivez pas, cliquez à gauche à l’écran d’accueil Windows sur l’espèce de petite roue et sélectionnez “Show keyboard”, un clavier virtuel va s’afficher et vous pourrez cliquer sur les touches.

Passez l’activation de windows il n’y en a pas besoin.

Pour éviter que sa copie arrive à expiration le mieux est de faire un Snapshot (sauvegarde de l’état de la Machine virtuelle à un instant T) dès la première installation de votre machine virtuelle.

Je dois dire que c’est plutôt sympa, car je peux coder sur mon Mac tout en testant le résultat sous IE comme si c’était une appli Mac.

NB: Si vous lancez un serveur web sous votre Mac et n’arrivez pas à y acceder depuis le navigateur IE, lancez le serveur sur le port 80 et l’ip de votre machine (192.168…..)

Arnaque sur le bon coin – numéro surtaxé à rappeler

samedi 17 novembre 2012 à 23:41

L’autre jour un proche a décidé de vendre son véhicule, comme la plupart des gens il se rend sur leboncoin.fr pensant avoir une réponse rapide. Pour aller plus vite il a laissé son numéro de téléphone.

24 heures après pas une touche mais il reçoit un sms:

Nous somme interressés par l’annonce de votre voiture sur leboncoin, veuillez nous contacter au 08……

Coup de bol il a flairé l’arnaque mais imaginez le pauvre type qui doit vendre à tout prix un truc et qui reçoit ça, l’envie de vendre, le côté pressé, etc…
Le taux de transformation doit être super.
Si en plus au bout on a un répondeur qui vous demande de patienter ou d’appuyer sur la touche 5 pour être mis en relation avec un interlocuteur…
En plus le sms était bien personalisé (nom du site, type de bien vendu).

Pour rappel:
Les numéros surtaxés commencent en général par 08 et vous prélèvent 1 eur ou plus à l’appel + 30/40 cents par minutes sur votre facture téléphonique, les tarifs peuvent varier.

L’envoi de sms par gros volumes est de l’ordre de quelques centimes (0.06 voire moins) alors que l’arnaque peut rapporter jusquà 80, 90 % de l’appel (1 euros ou plus) et autant pour chaque minutes passées. Y a de la maille à se faire…

Qu’est-ce que je suis bien depuis que j’ai plus de mobile…

“ERROR: VIRTUALENVWRAPPER_LOG_DIR is not set” et “ImportError: cannot import name urandom”

samedi 17 novembre 2012 à 14:22

Petits bugs pour virtualenwrapper sous Ubuntu. Ca se corrige facilement.

Ajoutez dans .bashrc pour corriger le premier:

export VIRTUALENVWRAPPER_LOG_DIR="$WORKON_HOME"
export VIRTUALENVWRAPPER_HOOK_DIR="$WORKON_HOME"

Pour le second, il faut relancer la création de l’env, sur l’env lui-même. Si votre env s’appelle “mon_env”, faites:

mkvirtualenv mon_env

Il faut les mêmes paramètres qu’à la création de l’env.

Créer un setup.py et mettre sa bibliothèque Python en ligne sur Pypi

vendredi 16 novembre 2012 à 19:06

Je crois que ce sujet est dans le top 10 des trucs qui paraissent mystiques même après avoir passé des heures sur les docs sur le net. Et si ça prend effectivement un peu de temps CPU neuronale pour s’en sortir, on est loin de la montagne qu’on s’en est fait.

Scénario: vous avez écrit une lib. Elle est belle, elle sent bon le sable chaud. Vous voulez la partager.

La première étape, c’est de créer une fichier setup.py qui permettra aux gens de l’installer. La seconde, c’est de la mettre en ligne sur le site Pypi pour que les gens puissent l’installer avec pip.

Nous allons donc créer un setup.py pour une lib incroyable: la “sm_lib”.

Arborescence

Généralement, quand on développe une petite lib au fil de l’eau, on une forte tendance à tout mettre en vrac dans un dossier. Cependant pour créer un paquet installable, il est beaucoup plus simple et propre d’avoir une organisation de fichiers standards. On peut faire sans, mais c’est prise de tête.

Prenons notre lib exceptionnelle…

Pour le moment, elle est composée d’un dossier “sm_lib” avec 3 fichiers:

#!/usr/bin/env python
# -*- coding: utf-8 -*-
 
 
from datetime import datetime
 
 
def proclamer():
    print "[%s] Sam et Max, c'est bien" % datetime.now()
 
 
if __name__ == "__main__":
    proclamer()

Maintenant que nous avons changé de mentalité, nous voulons absolument propager notre nouveau message et ton du blog partout, donc on va distribuer cette bibliothèque.

Premièrement, on va réorganiser les fichiers et en rajouter quelques uns:

On met sm_lib dans un dossier sm_lib

Vous noterez qu’on a mis notre dossier de lib, dans un autre dossier, et que les deux dossiers portent le même nom “sm_lib”. C’est redondant, mais c’est normal. Le dossier qui contient tout est le dossier de distribution, c’est l’emballage de notre lib. Le dossier qui contient notre code, c’est le dossier d’installation, c’est celui qui sera copié sur le système, et qui doit avoir un nom de package importable (pas de uniquement des lettres et des _ dans le nom, ou un chiffre mais pas en premier caractère).

Les noms peuvent être différents, mais généralement on donne le même nom aux deux, car c’est plus simple.

On rajoute 3 fichiers:

Pour le moment nos trois fichiers sont vides.

Choix des outils

Une des difficultés principales dans la distribution d’un code Python, c’est l’abondance de solutions. Pour l’installeur, on peut choisir entre distribute, setuptools, distutils ou Distutils2.

Je vous passe les détails, mais j’ai essayé les 4. distutils est trop vieux. distribute va être remplacé par distutils2 qui lui est encore très jeune. La seule solution qui passe partout pour le moment c’est setuptools. Tarek Ziade va faire la gueule, mais c’est ce que je recommande d’utiliser pour le moment. Je metterai à jour cet article pour utiliser un setup.cfg et des moyens plus modernes quand tout ça sera devenu la solution de facto, mais je ne vais pas pousser à la migration.

Donc vous allez utiliser setuptools.

Ensuite on utilise un fichier MANIFEST.in pour lister les fichiers non Python. On pourrait tout passer en paramètres à la main, mais le manifeste est la solution la plus productive.

Enfin on utilise un fichier markdown. ReST est le standard en Python, mais il est compliqué (je me suis tapé suffisament de doc sphynx pour témoigner), et pas géré par Github par défaut. Markdown ressort bien sur Pypi même sans conversion en HTML, donc on va garder ce format.

Oh, et ça va sans dire, mais ça va mieux en le disant, on va distribuer les fichiers sous forme de source pure, pas sous forme d’exe ou d’egg. C’est installable avec pip sur toutes les plateformes, et ça évite bien des prises de tête.

Rendez votre paquets user friendly

La première chose à faire, avant de mettre en ligne, c’est de rendre votre paquets facile à utiliser. Assurez-vous d’avoir les docstrings qui vont bien, et faciliter les imports.

Par exemple, dans notre __init__.py, on va rajouter:

from core import proclamer

Ainsi, l’utilisateur pourra faire:

from sm_lib import proclamer

au lieu de :

from sm_lib.core import proclamer

Faites cela uniquement pour les fonctions et classes les plus utiles. C’est un détail, mais ça rend l’expérience plus agréable.

Ensuite, si l’utilisateur est dans son shell, il va utiliser l’autocompletion pour découvrir votre lib. Il va se balader, et spammer “tab” pour voir “ce qu’il y a dedans”.

Pour faciliter ce process, limitez ce qui est importable avec __all__:

#!/usr/bin/env python
# -*- coding: utf-8 -*-
 
 
from datetime import datetime
 
__all__ = ['proclamer']
 
 
def proclamer():
    print "[%s] Sam et Max, c'est bien" % datetime.now()
 
 
if __name__ == "__main__":
    proclamer()

Ainsi, seul proclamer() sera importable depuis le module core. En effet, en important datetime, vous l’insérer dans le namespace de core, et donc il sera importable en faisant from sm_lib.core import datetime, et il apparaîtra dans l’autocompletion. Ici ça parait dérisoire, mais sur les grosses libs, ça fait beaucoup de bruit.

__all__ est une liste strings qui contient les noms de tout ce qu’on autorise à importer depuis ce module. Utilisez le pour rendre votre API d’import propre comme la chatte de… comme un sous neuf pardon. Désolé, par encore habitué à parler la novlang. On s’y met. On s’y met.

Pour finir on met les docstrings qui vont bien:

Ainsi l’utilisateur qui va installer votre lib s’y retrouvera très facilement en utilisant la fonction help(). Même sans doc et hors ligne.

__init__.py (on rajoute aussi l’en-tête d’encoding vu que la docstring contient des caractères non-ASCII):

#!/usr/bin/env python
# -*- coding: utf-8 -*-
 
"""
    Ce module proclame la bonne parole de sieurs Sam et Max. Puissent-t-ils
    retrouver une totale liberté de pensée cosmique vers un nouvel age
    reminiscent.
"""
 
__version__ = "0.0.1"
 
from core import proclamer

On a aussi rajouté la version, car il n’y a rien de plus chiant que d’avoir un bug sur une lib et de ne pas savoir de quelle version il s’agit. Il va falloir maintenir cette variable à jour.

Et core.py:

#!/usr/bin/env python
# -*- coding: utf-8 -*-
 
"""
    Implémentation de la proclamation de la bonne parole.
 
    Usage:
 
    >>> from sm_lib import proclamer
    >>> proclamer()
"""
 
from datetime import datetime
 
__all__ = ['proclamer']
 
 
def proclamer():
    """
        Fonction de proclamation de la bonne parole. Aucun paramètre, et
        retourne None, car tout le monde say que "Ex nihilo nihil"
    """
    print "[%s] Sam et Max, c'est bien" % datetime.now()
 
 
if __name__ == "__main__":
    proclamer()

Je vous passe le pamphlet sur les tests, c’est plusieurs articles rien que pour expliquer le pourquoi du comment. C’est mieux si vous en avez, mais si vous n’en avez pas, ne vous empêchez pas de publier, ça peut se rajouter au fur et à mesure.

Petite remarque en passant: je met toute la doc en français pour que vous compreniez le principe, mais si vous publiez un truc, je vous recommande chaudement de tout écrire en anglais de A à Z (variables, fonctions, modules, docstrings, comments, readme, doc, tests, etc). Sans quoi votre audience sera limitée au nombre de francophones qui programment, et en Python, et qui ont le niveau pour intéresser aux libs externes. Autant dire l’équivalent de l’audience ridicule de ce blog.

README

Dans le fichier README.md, qui est un fichier texte ordinnaire, assurez-vous de mettez les choses suivante:

Nous allons mettre le texte au format markdown. C’est un format très simple qui a le double avantage d’être automatiquement transformé en HTML par Github, et qui est bien lisible même quand il reste brut, tel qu’il sera affiché sur Pypi.

Dans notre cas, README.md va ressembler à un mélange des docstrings, un peu amélioré:

SM Lib - Proclame la bonne parole de sieurs Sam et Max
========================================================

Ce module proclame la bonne parole de sieurs Sam et Max. Puissent-t-ils
retrouver une totale liberté de pensée cosmique vers un nouvel age
reminiscent.

Vous pouvez l'installer avec pip:

    pip install sm_lib

Exemple d'usage:

    >>> from sm_lib import proclamer
    >>> proclamer()

Ce code est sous licence WTFPL.

MANIFEST.in

Le fichier va contenir une liste de tous les fichiers non Python qu’on veut inclure dans le package. Dans notre cas, la photo et le README.

include *.md
recursive-include sm_lib *.jpg

La syntaxe est elle aussi très simple, et utilise la notation des globs “*”.

La première ligne dit d’inclure tout fichier dans le nom est “n’importe quoi”.md. Il va inclure le README.
La seconde ligne dit d’inclure récursivement tout fichier dans le dossier sm_lib et ses sous-dossiers qui est nommé “n’importe quoi”.jpg. Il va inclure notre photo.

On peut mettre plusieurs lignes, et plusieurs motifs sur chaque ligne. Il n’est donc pas rare de voir des fichiers qui ressemblent à ça:

include *.txt *.rst
recursive-include dir1 *.txt *.rst
recursive-include dir2 *.png *.jpg *.gif
recursive-include dir2 *.css *.js *.coffee

Setup.py

C’est la partie difficile. Le fichier setup.py contient une fonction qui va magiquement installer votre lib, et il faut lui passer des paramètres et l’appeler. Le problème c’est que cette fonction compte 34 (à ma connaissance) arguments.

Vous pouvez mettre n’importe quel code Python dans le setup.py, mais généralement la fonction setup() suffit.

Je vais mettre dans ce setup.py les paramètres que vous utiliserez les plus souvent:

#!/usr/bin/env python
# -*- coding: utf-8 -*-
 
from setuptools import setup, find_packages
 
# notez qu'on import la lib
# donc assurez-vous que l'importe n'a pas d'effet de bord
import sm_lib
 
# Ceci n'est qu'un appel de fonction. Mais il est trèèèèèèèèèèès long
# et il comporte beaucoup de paramètres
setup(
 
    # le nom de votre bibliothèque, tel qu'il apparaitre sur pypi
    name='sm_lib',
 
    # la version du code
    version=sm_lib.__version__,
 
    # Liste les packages à insérer dans la distribution
    # plutôt que de le faire à la main, on utilise la foncton
    # find_packages() de setuptools qui va cherche tous les packages
    # python recursivement dans le dossier courant.
    # C'est pour cette raison que l'on a tout mis dans un seul dossier:
    # on peut ainsi utiliser cette fonction facilement
    packages=find_packages(),
 
    # votre pti nom
    author="Sam et Max",
 
    # Votre email, sachant qu'il sera publique visible, avec tous les risques
    # que ça implique.
    author_email="lesametlemax@gmail.com",
 
    # Une description courte
    description="Proclame la bonne parole de sieurs Sam et Max",
 
    # Une description longue, sera affichée pour présenter la lib
    # Généralement on dump le README ici
    long_description=open('README.md').read(),
 
    # Vous pouvez rajouter une liste de dépendances pour votre lib
    # et même préciser une version. A l'installation, Python essayera de
    # les télécharger et les installer.
    #
    # Ex: ["gunicorn", "docutils >= 0.3", "lxml==0.5a7"]
    #
    # Dans notre cas on en a pas besoin, donc je le commente, mais je le
    # laisse pour que vous sachiez que ça existe car c'est très utile.
    # install_requires= ,
 
    # Active la prise en compte du fichier MANIFEST.in
    include_package_data=True,
 
    # Une url qui pointe vers la page officielle de votre lib
    url='http://github.com/sametmax/sm_lib',
 
    # Il est d'usage de mettre quelques metadata à propos de sa lib
    # Pour que les robots puissent facilement la classer.
    # La liste des marqueurs autorisées est longue, alors je vous
    # l'ai mise sur 0bin: http://is.gd/AajTjj
    #
    # Il n'y a pas vraiment de règle pour le contenu. Chacun fait un peu
    # comme il le sent. Il y en a qui ne mettent rien.
    classifiers=[
        "Programming Language :: Python",
        "Development Status :: 1 - Planning",
        "License :: OSI Approved",
        "Natural Language :: French",
        "Operating System :: OS Independent",
        "Programming Language :: Python :: 2.7",
        "Topic :: Communications",
    ],
 
 
    # C'est un système de plugin, mais on s'en sert presque exclusivement
    # Pour créer des commandes, comme "django-admin".
    # Par exemple, si on veut créer la fabuleuse commande "proclame-sm", on
    # va faire pointer ce nom vers la fonction proclamer(). La commande sera
    # créé automatiquement. 
    # La syntaxe est "nom-de-commande-a-creer = package.module:fonction".
    entry_points = {
        'console_scripts': [
            'proclame-sm = sm_lib.core:proclamer',
        ],
    },
 
    # A fournir uniquement si votre licence n'est pas listée dans "classifiers"
    # ce qui est notre cas
    license="WTFPL",
 
    # Il y a encore une chiée de paramètres possibles, mais avec ça vous
    # couvrez 90% des besoins
 
)

Tester si tout marche bien

Si vous publiez du code, je vais partir du principe que vous utilisez au moins un virtualenv :-)

Donc, activez un environnement de test, et dans le dossier contenant setup.py, faites:

python setup.py install

Normalement votre lib devrait s’insaller dans votre env proprement. Vous devriez pouvoir faire dans un shell Python:

>>> from sm_lib import proclamer
>>> proclamer()
[2012-11-16 13:06:58.128545] Sam et Max, c'est bien

Et comme on a créé une commande, on doit aussi pouvoir faire depuis un terminal:

$ proclame-sm
[2012-11-16 13:08:18.763732] Sam et Max, c'est bien

Si vous regardez dans votre virtualenv, vous verrez que votre package a été ajouté. Sur ma machine il se trouve par exemple à ~/.virtualenvs/test/lib/python2.7/site-packages/sm_lib-0.0.1-py2.7.egg/sm_lib.

La photo doit-être dedans, ainsi que le code Python. La photo est un exemple important à comprendre et à faire marcher car c’est le manifeste que vous utiliserez pour tous les fichiers non Python: CSS, Javascript, Documentation, Images, Xml, Json, etc.

Publier sur Pypi

Cela va vous paraitre étonnant, mais tout le monde peut publier sur Pypi. Pourvu que le nom soit disponible, vous pouvez en fait uploader n’importe quoi. Même une lib de test comme celle-ci.

Entrez la commande (il faut avoir accès à internet):

$ python setup.py register

Ceci va inscrire votre lib dans leur listing. Et donnera une sortie qui ressemble à ça:

running register
running egg_info
writing sm_lib.egg-info/PKG-INFO
writing top-level names to sm_lib.egg-info/top_level.txt
writing dependency_links to sm_lib.egg-info/dependency_links.txt
writing entry points to sm_lib.egg-info/entry_points.txt
reading manifest file 'sm_lib.egg-info/SOURCES.txt'
reading manifest template 'MANIFEST.in'
writing manifest file 'sm_lib.egg-info/SOURCES.txt'
running check
We need to know who you are, so please choose either:
 1. use your existing login,
 2. register as a new user,
 3. have the server generate a new password for you (and email it to you), or
 4. quit
Your selection [default 1]: 

Choissisez 2. Il va vous permettre de créer un compte. Quand il vous demandera de sauvegarder vos identifiants pour un usage future, répondre oui vous permettra de ne pas rentrer votre mot de passe à chaque upload.

La prochaine fois vous pourrez choisir 1, puisque vous aurez un compte.

Si ça se coupe, relancez juste la commande. Le but étant d’obtenir ça:

Registering sm_lib to http://pypi.python.org/pypi
Server response (200): OK

Ce qui signifie que votre lib est inscrite sur Pypi (et que donc le nom était disponible, sinon il vous enverra chier et vous avez plus qu’à renommer votre lib).

Puis, il faut créer une distribution source (sdist) et le mettre en ligne (upload):

python setup.py sdist upload

Et voilà, votre lib est en ligne et installable avec pip !

Voici la page pypi, et la page gitub (ce qui n’a rien à voir, mais si vous voulez le code source…).

C’est finit. Si vous voulez uploader une nouvelle version de votre lib, il faut changer __version__ car Pypi n’accepte pas deux fois la même version.

Comment savoir qu’il est temps de faire une pause ?

jeudi 15 novembre 2012 à 21:34

Parfois on a la tête dans le guidon, et on ne sait pas trop quand il faut s’arrêter.

Voici un signe qui ne trompe pas:

  1. Vous retirez une pastille de poudre vaisselle de son emballage.
  2. Vous jetez la pastille, et vous mettez l’emballage dans la machine.
  3. Vous lancez la machine.

Je crois que je ne ferai donc pas d’article aujourd’hui.

Ah, trop tard.

En plus, j’ai appuyé sur le mauvais bouton, la machine n’est jamais parti.

I'm richer than you! infinity loop