PROJET AUTOBLOG


Sam & Max: Python, Django, Git et du cul

Site original : Sam & Max: Python, Django, Git et du cul

⇐ retour index

Mise à jour

Mise à jour de la base de données, veuillez patienter...

Floodsport…

jeudi 21 novembre 2013 à 08:50

Ceci est un post invité de 01ivier posté sous licence creative common 3.0 unported.

L’un des premiers “vrais” scripts que j’ai écrit en Python avait pour fonction de flooder une boite mail…

Pas très sympathique à première vue, mais c’est sans compter le fait que j’ai pris ma carte au club des gentils depuis plusieurs années…

Je floode donc dans la joie et la bonne humeur.

Tout d’abord, il m’a fallu identifier un moyen pas trop compliqué d’envoyer un mail.
J’ai donc récupéré un bout de code je ne sais où et j’ai viré tout ce qui dépassait :

# -*- coding: utf-8 -*-
 
import smtplib
from email.MIMEText import MIMEText
 
de_qui = 'ton@adresse.mail'
a_qui = 'son@adresse.mail' 
ton_server_smtp = 'smtp.ton.FAI'
 
message = MIMEText('Ceci est le corps du mail')      
message['Subject'] = 'Ceci est le titre du mail'                  
 
server = smtplib.SMTP(ton_server_smtp)                 
server.sendmail(de_qui, a_qui, message.as_string())   
server.quit()
print ("Le message a été envoyé avec un succès phénoménal !")

On reconnaît tout de suite le style qui caractérise les champions: pas de fonction, tout en ligne droite !
J’aimerai pouvoir vous dire ce qu’est MIMEText, mais ayant pu me débrouiller jusqu’ici sans le savoir… et bien je ne le sais pas. (Et ne comptez pas sur moi pour aller le chercher juste pour vous. J’ai une posture de mauvais élève à assumer.)

À ce niveau, sur ma Linux Mint, il me suffit de renseigner de_qui, a_qui et ton_server_smtp puis d’ouvrir un terminal là où se trouve mon script et de taper :

python go.py

(Oui, j’appelle souvent mes fichiers go.py. Comme ça j’ai l’impression qu’ils vont partir plus vite. Essayez, vous verrez. On y croit vraiment. Il faut juste s’habituer à appuyer un peu plus fort que d’habitude sur “entrer” tout en hurlant “GO !”. Mais l’effet est garanti.)

Si le message a bien “été envoyé avec un succès phénoménal” alors, quelque part dans l’univers, une boite mail a reçu un petit courrier ayant pour titre “Ceci est le titre du mail” et pour contenu “Ceci est le corps du mail”.
Je vous assure que je ne suis jamais aussi heureux de m’envoyer un mail que de cette façon.
Parfois je change l’objet pour me faire une surprise et je suis content.
Ça marche à chaque fois.

C’est à ce moment que l’on parle de petits chiens.

Maintenant que je savais envoyer un mail, il me fallait trouver un moyen de convertir la photo d’un petit chien en ASCII-art (rapport à la joie et la bonne humeur du flood, souvenez-vous).
J’ai trouvé mon bonheur avec le projet AA.

sudo apt-get install python-aalib

Paf !

J’ai récupéré ici un bout de code dont j’ai compris juste l’essentiel (où changer l’image, la largeur et la hauteur) et mon style tout en finesse a fait le reste :

import aalib
import Image
 
pix = 'toutou.jpg'
nb_lettre_largeur = 80
nb_lettre_hauteur = 40
 
screen = aalib.AsciiScreen(width = nb_lettre_largeur, height = nb_lettre_hauteur)
image = Image.open(pix).convert('L').resize(screen.virtual_size)
screen.put_image((0, 0), image)
print (screen.render())

“GO ! GO !”

python gogo.py

Ici aussi, une joie authentique est au rendez vous à chaque tentative.
C’est merveilleux.

Où l’on mélange les torchons et les torchons…

Je savais comment envoyer un mail.
Je savais comment convertir une photo de petit chien en ASCII.

La suite découlait de source.
Il me fallait désormais unifier le tout pour pouvoir envoyer des dizaines de mails à la même adresse de manière à ce que la photo du petit chien apparaissent dans le client de messagerie de mon destinataire grâce à l’empilement des titres des messages en partant du principe qu’il utiliserai une police à chasse fixe pour l’affichage.
Tout ce qu’il y a de plus classique.

À l’époque, sur gMail, le thème “Terminal” proposait une police monospaced verte sur fond noir du plus bel effet.
Mais ce n’est plus le cas.
Heureusement, en plagiant l’interface de gMail, Yahoo a aussi plagié le thème “Terminal” avec la police qui nous intéresse.
Voici donc le petit chien que je me suis envoyé sur un compte créé pour l’occasion.

Tootoo for yahoo

Ne me dites pas que ça ne vous donne pas envie de chialer.

Voici le script auquel j’ai (empiriquement) fini par arriver pour obtenir ce résultat émouvant :

# -*- coding: utf-8 -*-
 
# la lib smtp qui nous permet de dialoguer avec un serveur de mail
import smtplib
 
# pour simuler une irrégularité dans l'envoi
from time import sleep
from random import random
 
# nécessaire pour l'ASCII-Art
import aalib
import Image
 
import sys
from email.MIMEText import MIMEText
 
de_qui = 'À RENSEIGNER'        
a_qui = 'À RENSEIGNER'         
serveur_smtp = 'À RENSEIGNER'  
 
 
i = j = 25  # nombre de mail a envoyer donc de ligne,
nb = 81     # nombre de caractères par ligne, correspond au nombre de caractères
            # affichés par Yahoo pour un titre avec le skin "terminal"  
 
 
###############
## FONCTIONS ##
###############
 
 
def gotoascii(pix):    
 
    screen = aalib.AsciiScreen(width = nb-1, height = j)
    image = Image.open(pix).convert('L').resize(screen.virtual_size)
    screen.put_image((0, 0), image)
 
    # les replace() concernent des caractères qui sont gérés différemment 
    # des autres quand ils sont utilisés dans le tite d'un mail.
    return (screen.render().replace(' ', '.').replace(',', '.').replace(';','.'))
 
def essai(pix):
 
    # permet éventuellement de tester le rendu de l'image avant de l'envoyer
    print (gotoascii(pix))
 
def ligne(num_l, pix):
 
    # Comme il y a 'nb' élément par ligne, on compte de 'nb' en 'nb'
    # en fonction du numéro de la ligne renseigné par 'num_l' 
    return (gotoascii(pix)[nb*num_l:nb*(num_l+1)])
 
def send(num, pix):
 
    email = MIMEText("Qu'est-ce qu'on s'amuse !")
 
    # L'objet du mail est la ligne donnée en premier argument
    # de l'image ASCII donnée en deuxième argument
    email['Subject'] = ligne(num, pix)
 
    server = smtplib.SMTP(serveur_smtp)                 
    server.sendmail(de_qui, a_qui, email.as_string())   
    server.quit()                                       
 
 
#########################
## PROGRAMME PRINCIPAL ##
#########################
 
 
# Écoute le flag -test pour faire... des tests
# --> python go.py -test monImage.jpg
if sys.argv[1] == "-test": 
 
    essai(sys.argv[2])
 
else:
 
    while i > 0:
 
        # Augmente le délais et brise la régularité des envois de mail
        # afin d'éviter, peut-être, d'être black-listé par Yahoo :-p
        # Utilité purement hypothétique.
        sleep(20*random()+10)
 
        # Envoi le mail          
        send(i-1, sys.argv[1])                 
        if i == 1:
            print ("Mail n°{0} envoyé. Il n'en reste plus.".format(j+1-i))
        else:
            print ("Mail n°{0} envoyé. Il en reste encore {1}.".format(j+1-i, i-1))
        i -= 1
 
    print ("Bravo ! Cet envoi a été un succès !")

Pour l’utiliser, j’ai fait en sorte de pouvoir passer l’image à envoyer en argument.

python go.py monImage.jpg

J’ai écrit ce script il y a un peu plus de 2 ans, et, même si je progresse lentement, je me rends bien compte désormais, que je recalcule l’image à chaque mail .
Mais je vous l’ai laissé en l’état, car c’est tout aussi attendrissant qu’un chiot, je trouve.
Surtout qu’à part ça, le reste frôle la perfection (la gestion des arguments doit en laisser plus d’un rêveur, j’imagine).

Enfin, grâce à Sam & Max, j’ai découvert qu’il était possible d’utiliser d’autres photos que celle du petit chien.
Merci à eux.

flattr this!

Créer un super utilisateur Django sans prompt

mercredi 20 novembre 2013 à 10:23

Automatiser le déploiement d’un projet Django passe par un syncdb sans prompt, et donc pas de création de superutilisateur :

./manage.py syncdb --noinput

Vous pouvez bien entendu toujours en créer un plus tard, avec :

./manage.py createsuperuser --username=vous --email=votre_mail

Mais il va vous prompter pour saisir le mot de passe ou alors mettre un mot de passe inutilisable automatiquement, ça ne résout pas votre problème. Une astuce consiste à le créer avec un code Python et à piper ce code dans un shell :

echo "from django.contrib.auth.models import User; User.objects.filter(username='vous').count() or User.objects.create_superuser('vous', votre_email', 'mot_de_passe')" | ./manage.py shell

Personnellement je colle ça dans une tache fabric. Parfois on peut même générer le mot de passe aléatoirement avec un uuid qui est printé localement.

flattr this!

Marre des mots de passe pour push sur git ?

mardi 19 novembre 2013 à 09:36

Vous êtes dans une situation où vous ne pouvez pas utiliser uniquement une clé pour vous authentifier, et il faut taper votre putain de mot de passe à chaque push.

Ça sent le vécu n’est-ce pas ?

Mais bien entendu git vient avec une option bien cachée au fond de son fion pour adresser ce problème :

git config credential.helper 'cache --timeout=3600'

Et votre authentification sera gardée en mémoire pour une heure. Vous pouvez faire :

git config --global credential.helper 'cache --timeout=3600'

Pour l’étendre à tous les repos de votre machine.

flattr this!

You are deprecated

lundi 18 novembre 2013 à 09:20

Ceci est un post invité de Toniob posté sous licence creative common 3.0 unported.

Oh oui, je sais ce que vous allez me dire, et vous avez parfaitement raison. Oui, il m’arrive d’être un peu obtus sur certaines choses, surtout quand il s’agit d’un domaine que je connais. Bref, aujourd’hui nous allons parler de ifconfig et de route.

Soyons clair tout de suite : arrêtez d’utiliser ces merdes, elles sont dépréciées depuis longtemps ! Je sais comment sont les informaticiens de manière générale, et les administrateurs systèmes en particulier. Il est difficile de changer leurs habitudes. Mais si on vous proposait Scarlett Johansson, vous resteriez fidèle à Régine ou Jonathan Rhys Meyers si vous aviez Mickey Rourke ? Je vois à vos yeux lubriques que vous m’avez saisi. Alors c’est parti.

- ifconfig ? - ouiiiii ** tum tum tum tum **

Les interfaces

Utilisez la commande ip, c’est un ordre. Elle remplacera avantageusement ifconfig. Dans la suite de ce billet, je mettrai des exemples de commandes avec ifconfig et leur équivalent avec ip. Commençons avec du simple, afficher la liste des interfaces disponibles :

# ifconfig -a
eth0      Link encap:Ethernet  HWaddr 00:90:f5:ee:62:31
          UP BROADCAST MULTICAST  MTU:1500  Metric:1
          RX packets:0 errors:0 dropped:0 overruns:0 frame:0
          TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 lg file transmission:1000
          RX bytes:0 (0.0 B)  TX bytes:0 (0.0 B)
          Interruption:20 Mémoire:f7e00000-f7e20000

lo        Link encap:Boucle locale
          inet adr:127.0.0.1  Masque:255.0.0.0
          adr inet6: ::1/128 Scope:Hôte
          UP LOOPBACK RUNNING  MTU:65536  Metric:1
          RX packets:12 errors:0 dropped:0 overruns:0 frame:0
          TX packets:12 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 lg file transmission:0
          RX bytes:720 (720.0 B)  TX bytes:720 (720.0 B)
$ ip addr
1: lo:  mtu 65536 qdisc noqueue state UNKNOWN mode DEFAULT group default
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
2: eth0:  mtu 1500 qdisc pfifo_fast state DOWN mode DEFAULT group default qlen 1000
    link/ether 00:90:f5:ee:62:31 brd ff:ff:ff:ff:ff:ff

Vous voyez, pour le moment ce n’est pas si compliqué, vous économisez même de précieuses lettres. Vous constatez que la sortie est différente, mais vous y trouverez globalement les mêmes informations. C’est une question d’habitude. Personnellement, ça m’a pris un peu de temps, mais je ne reviendrais en arrière pour rien au monde.

On va maintenant assigner une adresse ip. Bon, j’avoue, c’est un peu plus long cette fois avec la commande ip :

# ifconfig eth0 192.168.1.1/24
# ip addr add 192.168.1.1/24 dev eth0

Et si maintenant nous ajoutions une adresse ipv4 ? Sauf qu’avec ifconfig, ce n’est pas possible, on ne peut le faire qu’avec ip :

# ip addr add 192.168.1.2/32 dev eth0

Si on affiche la configuration de l’interface réseau :

# ifconfig eth0
eth0      Link encap:Ethernet  HWaddr 00:90:f5:ee:62:31
          inet adr:192.168.1.1  Bcast:0.0.0.0  Masque:255.255.255.0
          UP BROADCAST MULTICAST  MTU:1500  Metric:1
          RX packets:0 errors:0 dropped:0 overruns:0 frame:0
          TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 lg file transmission:1000
          RX bytes:0 (0.0 B)  TX bytes:0 (0.0 B)
          Interruption:20 Mémoire:f7e00000-f7e20000
$ ip addr show eth0
2: eth0:  mtu 1500 qdisc pfifo_fast state DOWN group default qlen 1000
    link/ether 00:90:f5:ee:62:31 brd ff:ff:ff:ff:ff:ff
    inet 192.168.1.1/24 scope global eth0
       valid_lft forever preferred_lft forever
    inet 192.168.1.2/32 scope global eth0
       valid_lft forever preferred_lft forever

Et oui, rien du côté de ifconfig. Il ne voit pas que l’interface dispose de deux adresses différentes. Alors qu’il fallait utiliser des alias d’interface avec ifconfig, plus de souci de ce côté là avec ip. Voici maintenant quelques exemples d’autres commandes pouvant être utiles :

# ifconfig eth0 mtu 9000
# ip link set eth0 mtu 9000

# ifconfig eth0 up
# ip link set eth0 up

Les routes

Passons maintenant aux routes. Si vous utilisez ifconfig, vous vous servez aussi probablement de route. C’est fini les conneries maintenant ! Commençons par les afficher :

# route -n
Table de routage IP du noyau
Destination     Passerelle      Genmask         Indic Metric Ref    Use Iface
192.168.1.0     0.0.0.0         255.255.255.0   U     0      0        0 eth0
$ ip route
192.168.1.0/24 dev eth0  proto kernel  scope link  src 192.168.1.1

Oui, la sortie est moins verbeuse par défaut. Ça devrait vous plaire pour vos scripts shell. Ajoutons maintenant une route par défaut :

# route add default gw 192.168.1.254
# ip route add defaut via 192.168.1.254

Et si on regarde le résultat de la commande ip route maintenant :

$ ip route
default via 192.168.1.254 dev eth0
192.168.1.0/24 dev eth0  proto kernel  scope link  src 192.168.1.1

Contrairement à route, ip route génère une sortie qui peut être copiée / collée dans un ip route add. Pratique pour dupliquer une conf sur un autre serveur. Pour ajouter une route vers un hôte ou un réseau en particulier :

# route add -net 192.168.2.0 netmask 255.255.255.0 gw 192.168.1.253
# ip route add 192.168.2.0/24 via 192.168.1.253

C’est une affaire de goût, mais je préfère largement la syntaxe de ip à celle de route.

Conclusion

Voilà cette petite introduction à la commande ip est terminée. Essayez de remplacer ifconfig dans vos usages au quotidien. Ça prend un peu de temps pour s’y faire, mais la syntaxe plus claire et les fonctionnalités disponibles permettent vite d’être plus rapide dans la configuration réseau d’une machine. Les exemples que j’ai donnés dans cet article devraient être suffisants pour 90% des usages. Si vous cherchez à vouloir en faire plus, il suffit d’ajouter l’option help à votre ligne de commande pour avoir des informations. Plus pratique que d’avoir à taper dans le man sans arrêt.

Si cet article vous plaît (merci de me faire des commentaires élogieux, c’est mon premier ici), j’essaierai de vous faire découvrir un peu plus la stack réseau sous Linux. Si les vlans sont connus, les bondings un peu moins, je pense que les macvtaps sont un mystère pour la plupart d’entre vous. Et tout se fait avec l’aide d’ip en plus, que demande le peuple ?

Et si la conf réseau ça vous saoule, je trouverai à m’énerver sur d’autres choses (le larousse n’a qu’à bien se tenir).

flattr this!

Quine en Python

dimanche 17 novembre 2013 à 08:05

Une quine en informatique, c’est un programme qui, quand il est exécuté, affiche un code source qui permet d’obtenir le même résultat. La plupart des quines affichent leur propre code. Évidement, ouvrir le fichier de code et l’afficher ne compte pas comme une quine valide…

C’est un exercice beaucoup plus difficile qui n’en à l’air, même si normalement tout langage turing complet en est capable.

Techniquement, la quine la plus courte en Python est un fichier vide, ce qui est une quine valide. Mais comme ce n’est pas très fun, voici un exemple court avec des vrais caractères ASCII dedans:

a='a=%s;print a%%`a`';print a%`a`

Notez l’emploie de variables qui ne servent à rien d’autre que d’optenir une forme de symétrie.

Une autre version plus longue :

 b='\\';g='"';p='%';s="b='%s%s';g='%s';p='%s';s=%s%s%s;print s%s(b,b,g,p,g,s,g,p)";print s%(b,b,g,p,g,s,g,p)

Beaucoup de quines utilisent ce principe de créer une chaîne contenant une partie du programme et d’afficher et évaluer la chaîne en même temps. Parfois avec des boucles :

x = ['print "x =", x', 'for m in x: print m']
print "x =", x
for m in x: print m

En Python, on peut évidement faire des variantes avec sys.write, exec, etc. Voici un article qui liste des snippets tordus et sympathiques pour y arriver.

Ça ne sert strictement à rien, mais c’est dimanche, personne ne va lire cet article de toute façon.

flattr this!

Error happened! 0 - count(): Argument #1 ($value) must be of type Countable|array, null given In: /var/www/ecirtam.net/autoblogs/autoblogs/autoblog.php:428 http://ecirtam.net/autoblogs/autoblogs/sametmaxcom_a844ada43a979e3b1395ab9acb6afafb84340999/?126 #0 /var/www/ecirtam.net/autoblogs/autoblogs/autoblog.php(999): VroumVroum_Blog->update() #1 /var/www/ecirtam.net/autoblogs/autoblogs/sametmaxcom_a844ada43a979e3b1395ab9acb6afafb84340999/index.php(1): require_once('...') #2 {main}