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...

Paramètres sympas pour pytest   Recently updated !

vendredi 29 janvier 2016 à 13:19

En Python, pas la peine de faire des tests sans pytest.

Et avec quelques options, pytest devient encore plus pratique:

py.test -vv --capture=no --showlocals --exitfirst

Détaillons.

-vv déclenche le mode extra-verbeux, qui affiche le nom de chaque test qui passe ainsi que plein de détails en cas d’échec.

--capture=no permet d’utiliser print() et pdb dans vos tests unitaires.

--showlocals affiche les variables locales de tout test qui échoue.

--exitfirst arrête les tests dès le premier échec plutôt que de faire toute la liste.

Grace au paramètre addopts, vous pouvez passez ces paramètres par défaut à py.test.

Soit par la variable d’environnement PYTEST_ADDOPTS, par exemple en mettant dans votre bashrc:

export PYTEST_ADDOPTS="-vv --capture=no --showlocals --exitfirst"

Ou en mettant dans le fichier de config (comme tox.ini)

[pytest]
addopts = -vv --capture=no --showlocals --exitfirst

Les plans à quatre ne sont pas mystérieux

jeudi 28 janvier 2016 à 12:09

Avec Comment arrivent les plans à 3 et Le sperme ça attache au fond, je vous avais déjà montré que les expériences sexuelles qu’on qualifie d’inhabituelles n’arrivent pas suite à des rituels d’incantations mystiques.

Il en va de même pour le plan à quatre.

Ce soir-là je raccompagne chez elle une demoiselle très expérimentée dans le domaine de la coquinerie. Arrivés devant le portail, l’attendent deux de ses amis qui, et c’est important, ne s’étaient pas concertés pour venir. L’un amène l’apéritif.

À ce stade-là, le quatuor en rut majeur n’est pas programmé.

Néanmoins, je connaissais les personnes. Je savais qu’elles étaient sexuellement à l’aise et avaient déjà fait des choses de ce genre: strip-poker, striptease, plan à trois… Leurs histoires sont connues, et certaines avaient couché ensemble.

J’ai donc mentalement pris note qu’un travail d’équipe était possible.

Nous avons servi quelques verres, sur des discussions anodines.

La maitresse des lieux annonce qu’elle a mal aux pieds, et me demande un massage, activité pour laquelle tout mon entourage sait que je suis très qualifié. On concocte nos propres huiles dans la famille.

Maitresse coquine partage son enthousiasme à haute voix, et invite sa consœur à essayer. Je change donc de pieds, et j’y vois une opportunité.

Je propose ainsi au 4e de profiter de l’occasion pour apprendre quelques mouvements afin de ne pas laisser les orteils de ma cliente précédente refroidir.

Là on a une bonne base : 4 adultes consentants et expérimentés, dans l’intimité d’un appartement, ayant bu, se tripotant les uns les autres.

Parti de là, le reste n’est que gamineries, littéralement. Fausses excuses pour se toucher plus haut, « t’es pas cap » et autre « allezzzzzz ». J’embrasse l’une. On pousse un peu les filles à s’embrasser.

C’est très peu subtil, personne n’est dupe, mais c’est la nature humaine : on ne peut pas juste dire « allez on s’encule ! ». Il faut un prétexte, fût-il bidon.

L’un fera celle qui est un peu gênée.

L’autre fera celui qui est un peu étonné.

Et c’est tout.

Notez encore une fois le contexte habituel :

Bref, ça baise, ça suce, ça lèche, ça caresse. Tout le monde est très gentil, sourit beaucoup. Un des acteurs a du mal à bander. C’est normal. Ces plans à plusieurs foutent la pression, et ça arrive régulièrement. Il faut rassurer la personne, et proposer des activités qui n’impliquent pas de pénétration en attendant.

Et là vous voyez, pas de mystère. Pas de secrets incroyables.

Je vous le répète : le sexe, c’est la dinette des adultes.

Installer des packages depuis le shell Python   Recently updated !

mercredi 27 janvier 2016 à 22:30

J’améliore tout le temps mon fichier de démarrage de Python.

Aujourd’hui je lui ai rajouté une petite fonction pour installer des packages avec pip depuis le shell. En effet, souvent il m’arrive de le lancer, puis d’importer un truc qui n’est pas là. Alors il faut sortir, installer, revenir.

Chiant.

Du coup :

def pip_install(*packages):
    """ Install packages diretly in the shell """
    for name in packages:
        cmd = [sys.executable, '-m', 'pip', 'install', name]
        if not hasattr(sys, 'real_prefix'):
            # Si pas dans un virtual env, install juste
            # dans le dossier utilisateur
            cmd.append('--user')
        subprocess.call(cmd)

Et dans le shell :

>>> pip_install('arrow', 'requests', 'minibelt')
>>> import arrow

Comment mocker une coroutine ?   Recently updated !

lundi 25 janvier 2016 à 11:34

Dans le guide sur les tests en python (que je dois toujours terminer, je sais…), je vous parle des objets mocks.

Si vous avez eu le plaisir de jouer avec asyncio, vous avez du noter que unittest.mock n’a aucun outil pour gérer gérer les coroutines.

En attendant que ce soit intégré à la stdlib, voici une petite recette :

import asyncio
from unittest.mock import Mock
 
# on utilise toute la machinerie du Mock original
class AMock(Mock):
 
 
    def __call__(self, *args, **kwargs):
        # sauf qu'à l'appel on créé une fonction coroutine
        @asyncio.coroutine
        def coro():
            # Qui fait le vrai Mock.__call__ (et donc popule l'historique 
            # des appels), mais seulement après l'évent loop l'ait éxécuté
            super(AMock, self).__call__(*args, **kwargs)
 
        # On appelle la fonction coroutine pour générer une coroutine
        # (les coroutines marchent comme les générateurs)
        return coro()

Je propose qu’en l’honneur de ce bidouillage, on l’appelle… mockoroutine !

Ca va s’utiliser comme ça:

mockorourine = AMock()
yield from mockorourine()

Après le yield from, mockorourine.call_count == 1, et mockorourine.assert_called_once_with()passe.

Si vous êtes en 3.5+, on peut même faire:

class AMock(Mock):
 
    def __call__(self, *args, **kwargs):
        async def coro():
            super(AMock, self).__call__(*args, **kwargs)
        return coro()
 
    def __await__(self):
        # on delegue le await à la couroutine créée par __call__
        return self().__await__()

Puis:

await AMock()

Enfin un moyen d’afficher une vidéo avec des cases à cocher (PyQt4 et OpenCV inside) 4

dimanche 24 janvier 2016 à 15:11

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

Bonsjours les amis,

J’espère que vous allez bien et que vous n’avez pas trop pensé que j’étais mort rapport au fait que ça faisait longtemps que je n’avais pas posté d’article.

 

Où je mentionne plusieurs fois le mot JavaScript.

Le fait est que j’étais trop occupé à faire du JavaScript.

Bon, ce n’est pas exactement vrai, mais, je voulais vérifier une théorie selon laquelle dès qu’on parle de JavaScript sur Sam&Max, le nombre des commentaires explosent (je n’ai pas de théorie sur le fait qu’il faille l’écrire en gras, mais je trouve ça joli (sauf quand il y en a partout (parce qu’après ça fait trop))).

Mais, dire que j’étais trop occupé à faire du JavaScript n’est pas précisément faux non plus dans la mesure où je me suis mis à p5.js, qui est au JavaScript ce que Processing est au Java, à savoir un environnement de développement simplifié pour les pucelles et autres puceaux de la programmation.

p5.js qui m’a permis d’assouvir un de mes fantasmes : afficher un cheval qui court avec des cases à cocher dans une page web..

Un cheval qui court en cases à cocher d'après les célèbres photographies d'Easweard Muybridge, désormais dans le domaine publique.

Un cheval qui court en cases à cocher d’après les photos d’E.Muybridge, désormais dans le domaine publique.

Je vous ai mis un GIF animé, pour faire de l’animation, mais vous pouvez le voir en vrai ici avec vos cases à cocher à vous.

(Sauf pour celles et ceux pour qui ça ne marchera pas, bien évidemment.)

(Voilà pour la partie JavaScript. Je ne vais plus en parler. Les personnes concernées peuvent donc se rendre dès à présent à la section des commentaires. Merci.)

 

Où je m’attelle à une tâche bien plus sérieuse.

J’étais content, mais, passé ces enfantillages, il me fallait désormais m’atteler à une tâche bien plus sérieuse : afficher un cheval qui court avec des cases à cocher en Python.

Pour cela, j’ai choisi d’utiliser PyQt4 parce que c’est la meilleure librairie pour créer des interfaces graphiques en Python.

Ah Ah Ah…
Nan, mais, comme si j’en savais quelque chose…
C’est juste qu’un ami avait déjà réussi à afficher un bouton avec…
Donc, je me suis dit que c’était pour moi…
Bon, en fait, ce n’est pas pour moi…
Mais, que les choses soient claires, c’est l’informatique en général et la programmation en particulier qui ne sont pas pour moi…
Je veux dire, quand je vais lire Stack Overflow, j’ai de la peine pour moi…
C’est à dire que je me fais vraiment pitié tant je comprends que dalle…
Il m’est déjà arrivé de mettre une dizaine de secondes pour savoir si je lisais bien du Python (et s’en était)…
Nan, c’est moche…
Mais bon, je ne sais faire que de l’informatique (on me souffle à l’oreille que je sais aussi faire du Chirashi et c’est vrai)
Donc, je fais de l’informatique… (et du Chirashi)
Et j’en chie…
Mais à la fin je gagne…
Et je me paye même le luxe d’en faire un article sur S&M…
Pourquoi je vous raconte ça ?
Aucune idée…
Toujours est-il que j’ai choisi PyQt4
Que ça n’est pas pour moi…
Mais que [SPOILER ALERT] ça a fini par marcher…

 

Où j’affiche une fenêtre. UNE FE-NÊ-TRE. Oui messieurs, dames.

D’abord, il faut installer PyQt4

sudo apt-get install python-qt4

…et on ne peut pas dire que ce soit trop compliqué.

Et, voici le code minimal pour afficher une fenêtre :

#-*- coding: utf-8 -*-
from PyQt4 import QtGui
 
# On crée une appli Qt
application = QtGui.QApplication([])
# On fout quelque chose dedans
fond = QtGui.QWidget()
# On l'affiche
fond.show()
# On lance l'appli
application.exec_()

Les connaisseurs apprécieront mon désormais célèbre style procédural de champion du monde.
Mais bon. Ça marche où ça marche pas ?

Une fenêtre

Une fenêtre

Ça marche.

 

Où j’affiche un bouton dans la fenêtre.

Toujours en procédural, voici comment on ajoute un bouton à notre fenêtre (que l’on customize un peu au passage).
(J’insiste pour le procédural car, comme PyQt4 est conçu pour être utilisé en Programmation Orientée Objet, vous ne verrez pas ça tous les jours)

#-*- coding: utf-8 -*-
from PyQt4 import QtGui
 
app = QtGui.QApplication([])
 
# On crée un fond et lui donne une taille, une position sur l'écran et un titre
fond = QtGui.QWidget()  
fond.resize(300, 200)
fond.move(100, 100) 
fond.setWindowTitle("C'est formidable") 
 
# On crée un bouton sur notre fond et on lui donne une position sur celui-ci
bouton = QtGui.QPushButton('Mon petit bouton',fond)
bouton.move(80, 80)
 
fond.show()
app.exec_()

Et hop…

Un petit bouton dans une fenêtre

Un petit bouton dans une fenêtre

La première fois que ça a marché, j’ai cliqué 25 fois sur le bouton et j’en garde un très bon souvenir.

 

Où j’affiche plein de cases à cocher dans la fenêtre.

Bon, on peut afficher tout un tas de bordel dans une fenêtre, vous vous en doutez. Des images, du texte, des champs texte, des sliders, des menus déroulants, des labels, des séparations…
Mais, ça n’est pas le propos ici.
Nous ce qu’on veut, ce sont des cases à cocher. Plein de cases à cocher.

J’ai commencé par les placer dans une grille, mais, je me suis rendu compte qu’en leur donnant des positions absolues en pixels, il était possible de les faire se toucher, voire se chevaucher. Ce qui, quand on veut afficher un cheval, apporte un petit plus indéniable.
(chevaucher/cheval/humour)

Allons y donc pour nos cases à cocher.
(Je vous recolle tout à chaque fois parce que je sais qu’il y a des goulus parmi vous.)

#-*- coding: utf-8 -*-
from PyQt4 import QtGui
 
# On définie les dimensions de notre bazar
largeur = 40
hauteur = 30
tailleCase =14
 
app = QtGui.QApplication([])
 
fond = QtGui.QWidget()  
fond.resize(largeur*tailleCase+6, hauteur*tailleCase+6) # le +6 c'est pour tenir compte des marges
fond.setWindowTitle(u"Plein de cases à cocher") 
 
# On parcourt les ordonnées
for j in range(hauteur):
 
    # On parcourt les abscisses
    for i in range(largeur):
 
        # On crée une case à cocher sur notre fond
        check_box = QtGui.QCheckBox(fond)
        # Et on la positionne
        check_box.move(i*tailleCase, j*tailleCase)
 
fond.show()
app.exec_()
Le mot

Le mot “Joie” écrit à la main avec des cases à cocher.

 

Où j’affiche plein de cases à cocher dans la fenêtre mais en utilisant cette fois la Programmation Orientée Objet.

On arrive au bout. Mais, ce qu’il faut comprendre avec pyQt c’est que quand le programme arrive à l’instruction app.exec_() il démarre une boucle. On est alors un peu coincé pour parler avec l’interface.
Il est possible de cliquer sur les cases à la main, soit, mais, nous ce qu’on veut, c’est que ce soit un bout de code qui le fasse à notre place (car ayant bien mis 2 minutes pour composer une seule image affichant le mot “Joie”, j’ai des doutes pour le 25 fps).

Dans tous les cas, il n’est plus possible de rester en procédural. Voici donc la version POO du précédent script :

#-*- coding: utf-8 -*-
from PyQt4 import QtGui
import sys
 
largeur = 40
hauteur = 30
tailleCase = 14
 
class CheckBoxVideo(QtGui.QWidget):
 
    # On initialise la class, j'imagine...
    def __init__(self):
        super(CheckBoxVideo, self).__init__()
        self.interface()
 
    # On initialise l'interface    
    def interface(self):
 
        self.resize(largeur*tailleCase+6, hauteur*tailleCase+6)
        self.setWindowTitle(u"Plein de cases à cocher, mais en POO.")
 
        for j in range(hauteur):
 
            for i in range(largeur):
 
                check_box = QtGui.QCheckBox(self)
                check_box.move(i*tailleCase, j*tailleCase)     
 
        self.show()
 
 
if __name__ == "__main__":
      appli = QtGui.QApplication(sys.argv)
      ckbx = CheckBoxVideo()
      sys.exit(appli.exec_())
Le mot "Bonheur" écrit en cases à cocher mais en utilisant cette fois -ci la programmation orientée objet.

Le mot “Bonheur” écrit en cases à cocher mais en utilisant cette fois la programmation orientée objet.

J’ai ajouté un petit if __name__ == "__main__" histoire de laisser croire que je comprends ce que je fais.
Et puis j’ai intégré la librairie sys pour être conforme avec tous les exemples de tous les tutos que j’ai trouvé. Mais c’est vraiment par respect pour les devs qui se sont donné du mal à les écrire. Parce que, vous pouvez essayer, ça marche très bien sans.
Bref.

 

Où, en faisant ce qu’il ne faut pas faire, je constate qu’il ne faut pas le faire.

Je vous épargnerai la liste des trucs ridicules que j’ai essayé pour entrer dans cette boucle et modifier l’état des cases à cocher et n’évoquerai que les solutions que j’ai trouvé pour faire marcher mon bazar… pendant 20 secondes.

En effet, à force de chercher, je suis tombé sur ce fils de Stack Overflow où la réponse la mieux notée donne trois moyens différents de créer des threads avec Qt.

J’ai méticuleusement tout recopié à l’arrache et testé chacune des solutions.
Toutes m’ont permis de voir ma silhouette en cases à cocher avant de me retourner un délicat segfault au bout de 20 secondes.

Vraisemblablement, il y a quelque chose que je faisais mal.
Chose qui a été confirmée par un article intitulé : “You’re doing it wrong…”

C’est à ce moment que j’ai décidé de me coucher, vu que le Soleil se levait.

 

Où j’ai la confirmation que dormir peut s’avérer parfois utile pour se reposer.

Si j’étais mort dans mon sommeil ce jour là, mes derniers mots auraient été : “Putain de boucle de merde”.
Mais je me suis réveillé et je me suis dis que, tout de même, il devait y avoir un moyen simple de faire exécuter du code dans cette boucle principale.

Et là, avec un cerveau frais, je me suis souvenu de cet exemple expliquant comment animer une barre de progression.
Passer des valeurs à un objet pour en changer son état, c’est un peu ce que je cherchais à faire, non ?
Non.
C’était exactement ce que je cherchais à faire.

Le principe est de créer un timer et d’écouter ses tours d’horloge pour déclencher des événements.
À noter la nécessité d’importer QtCore pour cela.

#-*- coding: utf-8 -*-
from PyQt4 import QtGui, QtCore
import sys
 
largeurOut = 40
hauteurOut = 30
tailleCase = 14
 
 
class CheckBoxVideo(QtGui.QWidget):
 
    def __init__(self):
        super(CheckBoxVideo, self).__init__()
        self.interface()
 
    def interface(self):
 
        self.resize(largeurOut*tailleCase+6, hauteurOut*tailleCase+6)
        self.setWindowTitle("OMG ! Mais que se passe-t-il dans la console ?")
 
        for j in range(hauteurOut):
 
            for i in range(largeurOut):
 
                check_box = QtGui.QCheckBox(self)
                check_box.move(i*tailleCase, j*tailleCase)
 
        # On crée le timer.
        self.timer = QtCore.QBasicTimer()
        # Et on le lance en renseignant un délais pour chaque tour d'horloge.
        # Ici, 40 millisecondes, pour tenter (naïvement) d'obtenir du 25 images par seconde.
        self.timer.start(40, self)
 
        self.show()
 
    # Et voici la méthode qui écoute le timer.
    def timerEvent(self, e):
 
        print("Ce message va s'écrire en console toutes les 40 ms.")
 
 
if __name__ == "__main__":
      appli = QtGui.QApplication(sys.argv)
      ckbx = CheckBoxVideo()
      sys.exit(appli.exec_())
Des cases à cocher dans une fenêtre et des messages dans une console.

Des cases à cocher dans une fenêtre et des messages dans une console.

 

Où j’évoque ma jeunesse.

Il s’agissait maintenant de trouver un moyen de traiter du flux vidéo.
Mais comme je suis un ouf et que non seulement j’avais déjà réussi à afficher de la vidéo 3-bit dans mon terminal , mais qu’en plus je vous en avais fait part ici-même, et bien je suis allé copier/coller mon pâté. Tout simplement.

Pour celles et ceux qui n’ont pas eu la force psychologique de cliquer sur le lien, sachez que la solution que j’avais retenue à l’époque pour lire un fichier vidéo afin d’en traiter les données était OpenCV, et que c’est tout aussi pertinent maintenant.
(Enfin, ça marche. Ce qui, à mon niveau, est la définition même de la pertinence.)

 

Où il est de nouveau affiché un cheval qui court en cases à cocher, mais en Python cette fois.

Et voilà…
C’est terminé…

Voici le script après l’intégration du code exploitant OpenCV :

#-*- coding: utf-8 -*-
from PyQt4 import QtGui, QtCore
import sys
import cv2
 
largeur = 50
hauteur = 34
tailleCase = 14
 
# On crée une liste qui va stocker les QCheckBox
listeCB = []
 
# On définit un seuil pour pour cocher ou non les cases
seuil = 150
 
# On définit le fichier à lire.
video = cv2.VideoCapture('cheval_qui_court.mjpg')
 
class CheckBoxVideo(QtGui.QWidget):
 
    def __init__(self):
        super(CheckBoxVideo, self).__init__()
        self.interface()
 
    def interface(self):
 
        self.resize(largeur*tailleCase+6, hauteur*tailleCase+6)
        self.setWindowTitle(u"Un cheval qui court en cases à cocher")
 
        for j in range(hauteur): 
            for i in range(largeur): 
                check_box = QtGui.QCheckBox(self)
                check_box.move(i*tailleCase, j*tailleCase)
                # On ajoute chaque QCheckBox dans notre liste
                listeCB.append(check_box)   
 
        self.timer = QtCore.QBasicTimer()
        self.timer.start(40, self)
        self.show()
 
    def timerEvent(self, e):
 
        # On lit une frame de la vidéo
        ret,img = video.read()
        # On la passe en niveau de gris
        gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
        # On la retaille pour que le nombre de pixel correspond au nombre de cases à cocher
        gray = cv2.resize(gray, (largeur, hauteur)) 
 
        # On parcourt notre liste
        for index, checkBox in enumerate(listeCB):
 
            # On transforme les index en coordonnées            
            x = index%largeur
            y = index/largeur
            # On récupère le niveau de gris du pixel concerné
            valeur = gray.item(y, x)
 
            # En fonction de la valeur on coche ou non la case à cocher
            if (valeur > seuil):
              checkBox.setCheckState(0)
            else:
              checkBox.setCheckState(2)
 
            # Les plus attentifs auront remarqué que l'état de la case à cocher ne dépend pas d'un booléen.
            # En effet, il existe un état intermédiaire, le (1), que j'ai appelé l'état de Schrödinger, où 
            # la case à cocher est partiellement cochée. Un peu comme si elle était à la fois cochée et non cochée.
            # (Et j'interdis à quiconque d'évoquer, qu'en fait, elle n'est ni l'une, ni l'autre.)
 
 
if __name__ == "__main__":
      appli = QtGui.QApplication(sys.argv)
      ckbx = CheckBoxVideo()
      sys.exit(appli.exec_())

Et voici le cheval qui court en cases à cocher :

Je concède qu’arrivé là, il n’aurait pas été totalement farfelu d’ajouter un slider pour gérer le niveau du seuil.
Mais j’avais un peu peur de rendre le truc utile, vous voyez.
Donc j’ai laissé en l’état.

 

Où je conclue.

Je pense qu’il est assez clair désormais qu’il est possible de sauver l’Humanité en programmant en Python.
Je vous encourage donc à le faire.

À bientôt ou tard.

 

Où j’ajoute tout de même un bonus.

Et voici un cheval qui court avec des cases à cocher qui se chevauchent.
Ne me remerciez pas, ça me fait plaisir.

cheval

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/?54 #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}