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

pipenv, solution moderne pour remplacer pip et virtualenv 13

dimanche 8 octobre 2017 à 17:44

Kenneth Reitz, l’auteur de requests, tente régulièrement de nous refaire le coup du projet star. Ca n’a malheureusement pas très bien marché, et beaucoup de ses projets comme maya, records, crayon, tablib ou awesome n’ont pas vraiment connu de succès.

Entre alors pipenv, que j’ai testé il y a presque un an, et qui au départ montrait un beau potentiel, mais n’était pas encore très utilisable. J’ai fait quelques suggestions d’amélioration, comme permettre de choisir précisément la version de Python, et je me suis fait envoyé bouler. J’ai donc laissé l’auteur s’enterrer dans sa recherche de gloire passée.

Le hasard de reddit m’a remis pipenv sous le nez, et j’ai donc redonné sa chance au produit. Surprise, l’outil est maintenant très stable (plus de 2000 commits !) et mes propositions avaient même été intégrées.

Après ces 3 paragraphes vous vous demandez sans doute quand est-ce que je vais rentrer dans le vif du sujet, donc:

pipenv reprend les idées de pip, virtualenv, pew et même quelques trucs de npm, yarn, cargo, et essaye d’appliquer tout ça à Python. L’article suppose que vous savez ce que sont ces mots barbares, donc suivez les liens si ce n’est pas le cas.

pipenv permet donc d’installer des packages Python, d’isoler cette installation et de la rendre reproductible. Mais sans effort.

En effet, contrairement à la concurrence:

Installer pipenv

Contrairement à pip et virtualenv, pipenv n’est pas fourni avec une installation standard de Python, bien que l’outil soit maintenant recommandé par la doc officielle. Il va donc falloir l’installer. Or pipenv se base sur une version récente de pip, donc il faut d’abord être sûr d’avoir pip à jour.

Du coup:

# mise à jour de pip, mais juste au niveau utilisateur pour 
# pas casser le  system
python -m pip install pip --upgrade --user

Puis:

# installation de pipenv
python -m pip install pipenv --user

A moins d’être sous une Debian like type Ubuntu (qui demande un apt install de python-pip avant), tout le monde a pip installé avec une version moderne de Python.

Voilà, vous devriez avoir la commande pipenv disponible, ou pour ceux qui ont un système mal configuré, python -m pipenv.

Usage

Dans le dossier de votre projet:

pipenv install nom_du_package

C’est tout.

Si un virtualenv n’existe pas il sera créé. Sinon il sera utilisé. Les fichiers de configs sont gérés automatiquement, il n’y a rien à faire.

Si vous voulez lancer une commande dans le virtualenv:

pipenv run commande

Exemple:

pipenv run python

Va lancer le Python de votre virtualenv.

Si vous voulez que toutes les commandes soient dans le virtualenv:

pipenv shell

Et vous êtes dans un nouveau shell, dans le virtualenv. Ainsi:

python

Lancera celui de votre virtualenv.

On sort du shell avec Ctrl + D.

Vous pouvez arrêtez de lire l’article ici, c’est l’essentiel de ce qu’il y a à savoir.

Astuces

Si vous lancez pour la première fois dans un dossier pipenv avec:

pipenv --python x.x

Le virtualenv sera créé avec la version de Python x.x, pourvu qu’elle existe sur votre système. Setter la variable d’env PIPENV_DEFAULT_PYTHON_VERSION a le même effet.

Installer un package avec pipenv install --dev le marque comme dépendance de développement uniquement, et permet une installation séparée.

Vous pouvez aussi obtenir quelques infos utiles comme:

Enfin pipenv utilise pew, donc la magie de pew reste dispo, y compris la gestion de projets :)

Usage avancé

Si vous créez un fichier .env dans le dossier de votre projet tels que:

FOO=1
BAR=wololo

pipenv exécutera toutes ses commandes (y compris shell), avec FOO et BAR comme variables d’environnement.

La commande:

pipenv lock

Va créer un lock file. Ce fichier contient toutes les dépendances, et recursivement, les dépendances des dépendances, installées, avec leurs versions. On peut réutiliser ce fichier en prod pour installer une exacte copie de son setup local avec pipenv install. Sans ce fichier, pipenv install se comportera comme pip install.

Il y a plein d’autres trucs mais on va en rester là.

Regrouper ses fichiers de settings avec stow 12

vendredi 6 octobre 2017 à 10:24

Sous Linux, le dossier utilisateur est blindé de fichiers de configuration. Les fameux .machins. Par exemple le .bashrc pour la config du bash, le .mozilla qui contient toutes vos données Firefox, le .ssh avec toutes vos clés privées, le .local/share/virtualenvs avec les envs virtuels Python créés par pew ou .config/sublime-text-3 pour la configuration de Sublime text, etc.

Au final, voici tous les fichiers de conf qui sont importants pour moi de près ou de loin:

├── .autoenv
├── .bashrc
├── .config
│   ├── autostart
│   ├── Code
│   ├── copyq
│   ├── fish
│   ├── gtg
│   ├── liferea
│   ├── pulse
│   ├── stremio
│   ├── sublime-text-3
│   ├── transmission
│   ├── user-dirs.dirs
│   ├── user-dirs.locale
│   ├── variety
│   ├── VeraCrypt
│   ├── Zeal
│   └── zim
├── .django-completion.bash
├── .editorconfig
├── .git-aware-prompt
├── .git-completion.bash
├── .gitconfig
├── .gitignore
├── .git-prompt.sh
├── .git.scmbrc
├── .jupyter
├── .lastpass
├── .liferea_1.8
├── .local
│   └── share
        ├── gtg
        ├── keyrings
        ├── liferea
        ├── omf
        ├── TowerFall
        ├── virtualenvs
        └── Zeal
├── .mozilla
├── .netrc
├── .oh-my-zsh
├── .openambit
├── .pypirc
├── .scmbrc
├── .scm_breeze
├── .sshplus
├── .vscode
│   └── extensions
└── .zshrc

Quand on bidouille, on les change souvent. On les backup aussi, pour pouvoir les porter d’un laptop à un autre, les synchroniser, les uploader sur un serveur ou les récup lors d’une réinstallation. Parce que quand on a tuné ses terminaux et éditeurs aux petits oignons, on a pas envie de recommencer à poil.

Pour bien faciliter les choses, ils sont éparpillés un peu partout, dans des sous-dossiers différents.

Et je sais pas quel vil individu a suggéré une fois que faire une partition séparée pour /home était la solution de Skippy à tous les soucis, mais perso, ça me cause plus de bugs qu’autre chose quand on change de versions d’OS.

Bref, laissez tomber vos vieilles croyances issues de charlatans de sectes. Moi, j’ai vu la lumière (lien de don bitcoin en bas à droite de la page), et elle s’appelle GNU stow.

Stow est un vieil utilitaire (donc sagesse millénaire des anciens, vous pouvez avoir confiance, prenez ce cristal aussi il est en promo), qui est grosso merdo un ln -s récursive. C’est-à-dire que ça fait des symlinks des fichiers et des dossiers que vous lui passez.

On peut l’utiliser pour plein de choses, mais l’usage sacré implique le sacrifice d’une vierge à Max, puis de déplacer tous les fichiers de settings qu’on souhaite gérer dans un seul dossier.

Par exemple, moi j’ai:

/home/user/church/settings/

    ├── .autoenv
    ├── .bashrc
    ├── .config
    │   ├── autostart
    │   ├── Code
    │   ├── copyq
    │   ├── fish
    │   ├── gtg
    ...

Au lieu de les avoir éparpillées partout, toutes les brebis sont maintenant regroupées dans une seule église.

Il est très important de garder l’organisation des dossiers et des sous-dossiers d’origine. Ici vous voyez que j’ai le dossier Code, qui est le dossier de settings de VSCode. Mais il est DANS un dossier .config, car avant mon regroupement il était dans /home/user/.config/.

En revanche, il n’est pas du tout nécessaire que .config contienne tous les dossiers qu’il avait précédemment. Seuls ceux qui vous intéressent. Le reste peut rester à sa place initiale, dans le /home/user/.config/.

Donc je résume:

Arrive le messie, Stow.

D’abord, il faut l’installer, mais comme c’est un outil vénérable, il est dans les dépôts. Sous Ubuntu, le psaume “apt install stow” fera l’affaire.

Ensuite, on prêche. Je me perds dans mes propres paraboles, mais les voies du seigneur sont impénétrables, contrairement à celles d’Abella Anderson. Bref on demande à stow de traiter récursivement tout le contenu du dossier settings qui est dans /home/user/church afin de le linker vers /home/user/:

stow -d /home/user/church -t /home/user/ settings

Stow va prendre récursivement tous les dossiers qui sont dans /home/user/church/settings, et les comparer à ceux dans /home/user. Si ils existent, il va ne rien faire, mais si ils n’existent pas, il va créer un lien vers chacun de ceux manquants. Pour les fichiers, si ils n’existent pas, il va créer un lien, sinon il va vous afficher une erreur, afin de ne pas écraser quelque chose d’important et vous signalez qu’il y un souci.

Le but de tout ça ?

Pour votre système et tous vos logiciels, ça ne change rien. Ils vont tomber sur les liens et avoir l’impression que tous les fichiers de configs sont à leur place et vont continuer à fonctionner dans la joie et le gospel.

Et pour vous, ben vous avez un seul endroit où tous les fichiers importants sont regroupés. Plus besoin de les chercher. Facile à backuper et à restaurer. On peut même tout foutre sous Git.

Loué soit le sauveur.

Vive moi.

Jouer l’asticot sous les talons-aiguille, nouvel eldorado érotique 2

dimanche 17 septembre 2017 à 16:09

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

Préambule

Allongé de tout votre long par terre, encordé, saucissonné, enveloppé dans un drap ou du papier film alimentaire, vous allez découvrir que jouer le vers de terre ou l’asticot, ça fait autant de bien que de se l’astiquer. “ErotiQ LombriQ”, un jeu à pratiquer bien sûr sous les ordres de sa chère et tendre. Entre documentaire animalier et art ménagé.

Avant toute chose : nous sommes tous d’accord pour admettre que le plaisir de l’humiliation fait désormais parti du lifestyle de l’époque. A l’heure des déclarations vexatoires de Trump et des nouilles dans le slip de Hanouna, le sm est devenu un truc de Bisounours dans la mesure où là, tout est consenti.

Quel équipement ?

Pas de panoplie très élaborée. 2 ou 3 cordes achetées chez Bricorama suffiront amplement pour se faire saucissonner dans un premier temps. Vous pouvez aussi utiliser un drap dans lequel il faudra s’enrouler, façon rouleau de printemps. Il y aussi le wrapping, technique sm très en vogue en ce moment chez les dominas pro. Il s’agit de se faire immobiliser, envelopper intégralement de papier film, le même que celui qu’on utilise pour recouvrir un reste de spaghetti bolognaise à mettre au frigo. Seule la tête reste libre. Petit détail qui a son importance, lors de l’enroulement, le sboub doit-il être comprimé vers le haut ou vers le bas ? C’est à votre copine de trancher.

Pour toutes ces techniques, inutile que votre nana maitrise le bondage sur le bout des doigts même s’il faudra qu’elle ait envie d’être un zest directive ce soir là, nous y reviendrons.

Jouer le lombric, quel intérêt pour le mec ?

De prime abord, on s’imagine une pratique pénible, ramper façon entrainement militaire ou Koh Lanta, un mauvais bizutage ou une reconstitution flippante d’un Faite entrer l’accusé avec cadavre retrouvé enroulé dans le tapis persan de la grand-mère… Élargissez votre horizon, la « vers de terre attitude », c’est bien plus profond que ça.

figurine-de-collection-pixi-spirou-enroule-dans-un-tapis-6569-2015L’époque nous a transformé en robots multitâches, pressurisés comme jamais, chaque minute doit être rentable, chaque objectif rempli en temps et en heure, et plus vite que ça ! Il faut réussir sa life dans tous les domaines : être un king dans le taf, avoir pleins d’amis réels et virtuels, s’afficher en papa modèle et enfin assurer comme une bête au pieu, la bite à la main, toujours prêt (le mec n’a pas le droit de dire « non »). Au regard de ces constats, admettez que devenir une larve, une limace dénuée d’énergie, de cerveau, de bras, de jambes, de membres, peut s’avérer séduisant. Si les filles ont le droit de faire l’étoile de mer, les gars eux, ce sera donc le vers de terre.

Immobiliser ou presque, inutile de réfléchir, impossible de décider, d’agir, de contrôler, de faire des choix, c’est le grand soulagement, les vacances forcées, l’immense plaisir de la contrainte qui libère. Alors, vous pouvez philosopher : « je ne suis plus rien, je suis le lombric du monde ». Le lâcher-prise engendre le fameux subspace, cet état de conscience modifié procuré par les endorphines, bref, de quoi économiser quelques joints.

01Au raz du sol, vous ondulez avec vue imprenable sur les Bouboutin de votre meuf, ses jambes, ses bas-couture. Même le grand Bashung l’avait fantasmé dans sa chanson J’ai longtemps contemplé (album Chatterton)

“J’ai longtemps contemplé
Tibias, péronés
Au ras des rez-de-chaussée
Ces cités immenses
Où je ne rutilais pas
J’arpentais des tapis de braise…”

Mais attention, ce n’est pas le Club Med pour autant. Il va falloir essayer de bouger un peu, de se tortiller, avancer centimètre par centimètre, bref ramper tel un nuisible, pour atteindre le ridicule absolu ! Votre douce complice peut vous motiver en semant par terre des lombrics gélifiés trouvés au rayon Haribo, ou disséminer dans toute la pièce ses culottes sales ou encore des lignes de coke. Mais être saucissonné sous cocaïne, c’est un peu comme boire un Pétrus juste après s’être lavé les dents avec un dentifrice mentholé, c’est gâché !

Après vous avoir fait mordre la poussière, la meuf va vous obliger à jouer l’aspirateur à cunni. D’un coup de talon, la miss vous fera rouler sur le dos. Elle ne résistera pas à l’envie sadique de retirer son string histoire de vous faire admirer sa moquette, juste au dessus de votre tête. Toujours impossible de bouger un doigt, vous êtes à sa merci, et on dit merci qui ? « Merci Maîtresse ! » Dans sa grande mansuétude, elle se servira de vous comme d’un vulgaire sextoy en s’asseyant sur votre tronche, pour un facesitting d’anthologie. Attention tout de même à l’asphyxie, car enfoui sous ses fesses, difficile de bafouiller un safe word audible ou de faire un signe de secours, vu que vous n’avez plus de bras. À moins de se tordre comme un appât à deux doigts d’être accroché à l’hameçon de la pécheresse.

ver-une-caricature-stupide-fou-tee-shirts-t-shirt-hommeFaire mordre la poussière à son partenaire, quel intérêt pour la nana ?

Si les mecs ne peuvent pas échapper aux bimbos à plat ventre au détour d’un spam, d’un kiosque à journaux ou d’une pub dans le métro, pour les femmes, profiter de mecs dans le même état d’abandon, c’est beaucoup plus rare. Mais il y a quand même deux professions masculines où les filles ont la chance d’admirer quasi systématiquement un gars à quatre pattes voir à plat ventre, raie du cul apparente : plombier et dépanneur informatique. Ces derniers passent sous le bureau et se retrouvent nez à nez ou plutôt nez à pieds avec les escarpins aux talons parfois vertigineux.

Avoir un homme à ses pieds, lui demander n’importe quoi sans avoir à lui dire merci, ça peut être très excitant. C’est aussi une bonne façon de se foutre de sa gueule, de régler des vieux comptes, lui faire manger les acariens à ce vaurien, depuis le temps qu’il repousse le moment de passer l’aspi. « Les plates excuses, c’est fini ! Tu n’es qu’un insecte rampant. Ce soir, ce ne sera pas « baisons » mais baygon vert ! » (contre insectes rampants, cafards, fourmis, action immédiate et longue durée, comme dit la pub.)

Il peut être très plaisant de faire rouler le vermisseau sous ses pieds, un peu comme pousser un gros boudin, ça rappelle l’émission culte Interville. Et puis, comme expliqué plus haut, la demoiselle ou la dame pourra utiliser l’asticot tel un objet sexuel, en bonne entomologiste zoophile. Elle peut faire un trou dans le drap ou le papier film, juste au niveau du zboub.

353-0Mais votre amour propre est sauf, elle ne pourra pas vous traiter de « bite sur patte », puisque vous n’en avez plus, des papattes. Reste pour elle à s’empaler gaiement sur votre appendice. Concentrez-vous uniquement sur votre érection. Le reste n’a plus aucune importance vu le ridicule dans lequel vous êtes vautré, plus rien à réussir, plus d’objectif à atteindre, le nirvana post productiviste en somme.

 De notre contributrice Emma du blog Paris Derrière, blog sur les frasques du Paris érotique.

logo6

 

La course du bus de l’innovation sur le chemin de la croissance 6

samedi 22 juillet 2017 à 22:10

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

Bonsjours à toutes et à tous,

Dans un sursaut de patriotisme, je me suis dit qu’il me fallait, moi aussi, participer à l’effort national et promouvoir le savoir-faire technologique français. Partant du constat que, de nos jours, proposer quelque chose de nouveau semble suffisant pour être innovant, j’ai fait comme tout bon startupeur, je ne me suis pas embarrassé à concevoir quelque chose d’utile. À vrai dire, ce n’est même pas nouveau. Mais je suis français et j’ai un compte Twitter, je crois que c’est amplement suffisant pour prétendre au label #CitizenOfTheFrenchTechNation.

 
frenchtech

 

Où le bus l’innovation va tout droit.

Parce que je suis bien conscient de l’influence que cet article va avoir dans le monde du jeu vidéo, je vais détailler les différentes étapes de la réalisation de ce projet bouleversant.

Tout d’abord, j’ai fait en sorte que le bus de l’innovation aille tout droit sur un chemin de la croissance qui est tout droit.

#-*- coding: utf-8 -*-
 
# On importe de quoi dormir
from time import sleep
 
# On définit le graphisme en accord avec l'équipe de designers
chemin = " " 
arbre = "A"
bus = "B"
 
# On définit la qualité de l'image après avoir consulté les experts en GPU du Digital-Agile-Open-Tech-Lab-Responsive.IO
largeur_ecran = 70
 
# On définit l'état initial conjointement avec la team level design.
# (elle-même ayant sollicité au préalable le narrative designer, bien entendu)
largeur_chemin = 15
position_chemin = 28
position_bus = 35
 
while 1:
 
    # On place la première portion d'arbres dans le paysage
    paysage = arbre * position_chemin
    # On place le chemin
    paysage += chemin * largeur_chemin
    # On remplit le reste du paysage par la deuxième portion d'arbres
    paysage += arbre * (largeur_ecran - len(paysage))
    # On place le bus sur notre paysage
    paysage = paysage[:position_bus] + bus + paysage[position_bus:]
 
    # On affiche le tout
    print(paysage)
 
    # On dort un peu
    sleep(0.2)

bus_innovation_droit

Oui. Il est effectivement possible d’arriver plus simplement au même résultat, mais, mes qualifications ne m’offrent pas le loisir d’être incompétent. J’anticipe donc les futurs mouvements du bus de l’innovation ainsi que les inéluctables virages du chemin de la croissance.

Ce doit être un peu déroutant pour vous, j’en conviens, mais c’est l’expérience qui parle.

Faites-moi confiance.

 

Où le bus l’innovation va tout droit mais en bien plus beau.

Parce que l’on n’est jamais assez exigent sur l’apparence d’un produit de luxe, j’ai voulu changer le rendu des arbres en remplaçant le “A” par un “█” bien plus raffiné. Voici le résultat que j’ai obtenu :

bus_innovation_droit_arbre

Diable comme le succès est semé d’embûches !

En effet, un petit…

>>> len("█")
3

… m’a appris que le “█” comptait pour trois caractères, faussant mon ingénieuse gestion des positions.

Mon talent m’avait permis d’anticiper les mouvements et autres virages mais pas ça. Damned. Qu’allais-je faire ?

Un petit replace() bien placé et le tour était joué. Sans compter que je pouvais désormais me permettre de mettre de la couleur.

La classe internationale.

#-*- coding: utf-8 -*-
 
from time import sleep
 
chemin = " " 
arbre = "A"
#On définit un arbre classe et vert en utilisant les codes ANSI
arbre_classe_et_vert = "\33[32m█\033[0m"
bus = "B"
 
largeur_ecran = 70
largeur_chemin = 15
position_chemin = 28
position_bus = 35
 
while 1:
 
    paysage = arbre * position_chemin
    paysage += chemin* largeur_chemin
    paysage += arbre * (largeur_ecran - len(paysage))
    paysage = paysage[:position_bus] + bus + paysage[position_bus:]
    # PAF ! On remplace l'arbre ridicule par un arbre classe et vert après avoir géré la position des différents éléments.
    paysage = paysage.replace(arbre, arbre_classe_et_vert)
 
    print(paysage)
 
    sleep(0.5)

BIM !

bus_innovation_droit_arbre_vert

 

Où le bus de l’innovation va tout droit mais sur un chemin de la croissance qui tourne.

Pour faire tourner le chemin de la croissance je fais un petit +2/-2 sur sa position avec un randint(), et zou.

Par contre, pour forcer le chemin de la croissance à rester dans l’écran, j’ai été surpris de ne pas trouver de fonction prête à l’emploi pour contraindre un nombre dans un intervalle donné. Je suis donc passé par une “astuce” pécho sur Stack Overflow que j’ai trouvée élégante. On classe par ordre croissant le nombre donné avec les bornes de l’interval et on récupère le deuxième élément.

position = sorted(position_min, position, position_max)[1]

Si vous avez mieux, ça m’intéresse.

#-*- coding: utf-8 -*-
 
# On importe de quoi choisir des nombres au hasard
from random import randint
 
from time import sleep
 
chemin = " " 
arbre = "A"
arbre_classe_et_vert = "\33[32m█\033[0m"
bus = "B"
 
largeur_ecran = 70
largeur_chemin = 15
position_chemin = 28
position_bus = 35
 
# On définit une position maximale pour le chemin de la croissance
position_max_chemin = largeur_ecran - largeur_chemin
 
while 1:
 
    # On calcule la nouvelle position du chemin de la croissance
    # Un peu plus à droite, un peu plus à gauche ou un peu plus tout droit...
    position_chemin += randint(-2, 2)
 
    # En s'assurant qu'il ne déborde pas de la largeur de l'écran
    position_chemin = sorted([1, position_chemin, position_max_chemin])[1]
 
    paysage = arbre * position_chemin
    paysage += chemin * largeur_chemin
    paysage += arbre * (largeur_ecran - len(paysage))
    paysage = paysage[:position_bus] + bus + paysage[position_bus:]
    paysage = paysage.replace(arbre, arbre_classe_et_vert)
 
    print(paysage)
 
    sleep(0.5)

bus_innovation_chemin_virage

 

Où le bus de l’innovation crache des flammes.

Avant de me pencher sur les mouvements du bus de l’innovation, j’ai pris le temps de le tuner un peu.

Déjà, direct, je l’ai peint en rouge, rapport au fait que le bus de l’innovation, c’est un peu la Ferrari de l’entrepreneuriat.

Et puis, je me suis dit qu’il fallait qu’il n’y ai vraiment absolument aucun doute sur le fait que c’était bel et bien le bus de l’innovation. Je lui ai donc fait écrire “LE BUS DE L’INNOVATION” sur la route. Je m’en remets à vous pour me dire s’il reste une ambiguïté.

Accessoirement, le “A” utilisé pour placer les arbres est devenu un “a“, pour ne pas être confondus avec le “A” présent dans “INNOVATION”. C’est un détail, mais les générations d’ingénieurs qui liront ça dans deux cent ans seront bien contents de trouver cette explication.

#-*- coding: utf-8 -*-
 
from random import randint
from time import sleep
 
chemin = " " 
arbre = "a"
arbre_classe_et_vert = "\33[32m█\033[0m"
 
largeur_ecran = 70
largeur_chemin = 15
position_chemin = 28
position_bus = 35
 
# On définit le texte écrit par le bus de l'innovation
texte_du_bus = "LE BUS DE L'INNOVATION "
# On récupère le nombre de caractères dans le texte écrit par le bus de l'innovation
nb_caractere = len(texte_du_bus)
# On initialise un compteur pour gérer la succession des caractères
compteur = 0
 
position_max_chemin = largeur_ecran - largeur_chemin
 
while 1:
 
    position_chemin += randint(-2, 2)
    position_chemin = sorted([1, position_chemin, position_max_chemin])[1]
 
    paysage = arbre * position_chemin
    paysage += chemin * largeur_chemin
    paysage += arbre * (largeur_ecran - len(paysage))
 
    # Dans le texte écrit par le bus de l'innovation, on prend le caractère 
    # indiqué par le compteur modulo le nombre de caractères possibles
    caractere = texte_du_bus[compteur%nb_caractere]
    # On peint le caractère en rouge Ferrari
    bus = "\33[31m{0}\033[0m".format(caractere)
    # On incrémente le compteur pour avoir le caractère suivant au prochain tour
    compteur += 1
 
    paysage = paysage[:position_bus] + bus + paysage[position_bus:]
    paysage = paysage.replace(arbre, arbre_classe_et_vert)
 
    print(paysage)
 
    sleep(0.5)

Magnifique.

bus_innovation_flamme

 

Où l’on cherche à faire tourner le bus de l’innovation.

Je ne vais pas vous mentir, la course du bus de l’innovation sur le chemin de la croissance n’est pas vraiment une nouveauté vidéoludique. Nous, c’est à dire La Labomedia, l’avons déjà présentée à Toulouse lors du THSF 2014 ainsi qu’au PSESHSF 2016 de Choisy-le-Roi dont il existe même une vidéo de la Master Class.

Sur cette photo spectaculaire, vous pouvez découvrir la pertinence de notre ingénieuse interface biologique imputrescible nourrie aux anti-biotiques NF.

busdelinnovationsurlechemindelacroissance

Mais, non seulement j’avais perdu totalement le code initial mais en plus l’installation s’appuyait sur l’excessivement chère MakeyMakey qui, par ailleurs, telle qu’elle est vendue, impose à l’utilisateur d’être relié à une masse.

Pour sa résurrection, je lui ai donc préférée la Capacitive Touch HAT pour RaspberryPi conçue par Adafruit et qui fonctionne direct au simple touché.

(Il va de soit que les natural chicken flavor interfaces n’ont, elles, pas été remises en question.)

Voici le code minimal pour utiliser le Capacitive Touch HAT une fois la librairie d’Adafruit installée :

import Adafruit_MPR121.MPR121
from time import sleep
 
interface = Adafruit_MPR121.MPR121.MPR121()
interface.begin()
 
while 1:
 
  # Si la patine numéro 0 est touchée
  if interface.is_touched(0):
      print("GAUCHE !")
 
  # Si la patine numéro 10 est touchée
  if interface.is_touched(10):
      print("DROITE !")
 
  sleep(0.1)

Qui devient ceci quand on instaure un seuil de détection pour tenir compte de la conductivité des pattes de poulet.

import Adafruit_MPR121.MPR121
from time import sleep
 
interface = Adafruit_MPR121.MPR121.MPR121()
interface.begin()
 
seuil = 100
 
while 1:
 
  # Si la patte de poulet reliée à la patine numéro 0 est touchée
  if interface.filtered_data(0) < seuil:
      print("GAUCHE !")
 
  # Si la patte de poulet reliée à la patine numéro 0 est touchée
  if interface.filtered_data(10) < seuil:
      print("DROITE !")
 
  sleep(0.1)

On ne peut pas dire que ce soit très compliqué. À noter tout de même la nécessité d’activer l’I2C et de lancer le script en root. Une formalité pour celles et ceux qui ont de l’ambition dans la Vie.

Une fois intégré dans notre formidable simulation de sport mécanique extrême, le script ressemble alors à ça :

#-*- coding: utf-8 -*-
 
# On importe la librairie d'Adafruit
import Adafruit_MPR121.MPR121 as MPR121
 
from random import randint
from time import sleep
 
# On instancie l'interface...
interface = MPR121.MPR121()
# ... et on la démarre.
interface.begin()
 
chemin = " " 
arbre = "a"
arbre_classe_et_vert = "\33[32m█\033[0m"
 
largeur_ecran = 70
largeur_chemin = 15
position_chemin = 28
position_bus = 35
 
texte_du_bus = "LE BUS DE L'INNOVATION "
nb_caractere = len(texte_du_bus)
compteur = 0
 
position_max_chemin = largeur_ecran - largeur_chemin
 
seuil = 100
 
while 1:
 
    # En fonction des patines touchées,
    # on déplace le bus de l'innovation vers la droite...
    if interface.filtered_data(0) < seuil:
        position_bus += 1
 
    # ... ou vers la gauche.
    if interface.filtered_data(10) < seuil:
        position_bus -= 1
 
    position_chemin += randint(-2, 2)
    position_chemin = sorted([1, position_chemin, position_max_chemin])[1]
 
    paysage = arbre * position_chemin
    paysage += chemin * largeur_chemin
    paysage += arbre * (largeur_ecran - len(paysage))
 
    caractere = texte_du_bus[compteur%nb_caractere]
    bus = "\33[31m{0}\033[0m".format(caractere)
    compteur += 1
 
    paysage = paysage[:position_bus] + bus + paysage[position_bus:]
    paysage = paysage.replace(arbre, arbre_classe_et_vert)
 
    print(paysage)
 
    sleep(0.5)

bus_innovation_tourne

 

Où le bus de l’innovation est tenu de rester sur le chemin de la croissance.

Écoutez, que les choses soient bien claires, moi aussi je trouve cet article beaucoup trop long, mais c’est du rayonnement de la France dont il est question. Dois-je vous le rappeler ?

Voici donc comment j’ai tenu compte des sorties du chemin de la croissance par notre bus de l’innovation :

#-*- coding: utf-8 -*-
 
import Adafruit_MPR121.MPR121 as MPR121
 
from random import randint
from time import sleep
 
interface = MPR121.MPR121()
interface.begin()
 
chemin = " " 
arbre = "a"
arbre_classe_et_vert = "\33[32m█\033[0m"
 
largeur_ecran = 70
largeur_chemin = 15
position_chemin = 28
position_bus = 35
 
texte_du_bus = "LE BUS DE L'INNOVATION "
nb_caractere = len(texte_du_bus)
compteur = 0
 
position_max_chemin = largeur_ecran - largeur_chemin
 
# On définit un booléen qui rendra compte de l'état du bus de l'innovation
le_bus_roule = True
 
seuil = 100
 
while 1:
 
    if interface.filtered_data(0) < seuil:
        position_bus += 1
 
    if interface.filtered_data(10) < seuil:
        position_bus -= 1
 
    # Si le bus roule...
    if le_bus_roule:
 
        position_chemin += randint(-2, 2)
        position_chemin = sorted([1, position_chemin, position_max_chemin])[1]
 
        paysage = arbre * position_chemin
        paysage += chemin * largeur_chemin
        paysage += arbre * (largeur_ecran - len(paysage))     
 
        # Si le bus sort de la route, à gauche ou à droite...
        if position_bus <= position_chemin or position_bus >= position_chemin + largeur_chemin:
 
            # On change l'apparence du bus (qui devient une croix verte)
            bus = "\33[32mX\033[0m"
            # On change l'état du bus de l'innovation
            le_bus_roule = False
 
        # Sinon, on affiche le bus comme précédement défini
        else:
            caractere = texte_du_bus[compteur%nb_caractere]
            bus = "\33[31m{0}\033[0m".format(caractere)
            compteur += 1
 
        paysage = paysage[:position_bus] + bus + paysage[position_bus:]
        paysage = paysage.replace(arbre, arbre_classe_et_vert)
 
        print(paysage)
 
        # Si, entre temps, le bus de l'innovation s'est arrêté de rouler
        if not le_bus_roule:
 
            # On affiche un message sympathique après avoir sauté une ligne
            print("\nIl n'est pas exclu que le bus de l'innovation se soit pris un arbre...")
 
        sleep(0.5)

bus_innovation_crash

 

Où la course du bus de l’innovation sur le chemin de la croissance va pouvoir enfin commencer.

Afin que le public intègre bien le défi collectif que représente la relance de l’économie par le financement et le développement d’innovants nouveaux projets novateurs avec de la technologie à la pointe de la technologie, j’ai fait en sorte d’afficher la croissance totale que l’ensemble des joueurs auront fait parcourir au bus de l’innovation.

Ainsi, n’y a-t-il jamais un individu qui perd, mais toujours un collectif qui gagne.

Quelque chose entre la victoire éternelle et le succès permanent.

Une véritable leçon de Vie.

#-*- coding: utf-8 -*-
 
import Adafruit_MPR121.MPR121 as MPR121
 
from random import randint
from time import sleep
 
interface = MPR121.MPR121()
interface.begin()
 
chemin = " " 
arbre = "a"
arbre_classe_et_vert = "\33[32m█\033[0m"
 
largeur_ecran = 70
largeur_chemin = 15
 
# On met en place un système d'initialisation des positions
# du chemin de l'innovation et du bus de la croissance
init_position_chemin = 28
init_position_bus = 35
position_chemin = init_position_chemin
position_bus = init_position_bus
 
texte_du_bus = "LE BUS DE L'INNOVATION "
nb_caractere = len(texte_du_bus)
compteur = 0
 
position_max_chemin = largeur_ecran - largeur_chemin
 
seuil = 100
 
le_bus_roule = True
 
# On déclare des variables qui vont nous permettre de rendre compte
# des quantités de croissance parcourue par le bus de l'innovation
croissance_parcourue_totale = 0
croissance_parcourue = 0
 
# On définit un petit texte à formater pour présenter les quantités en question
texte_crash ='''
Bravo !
Tu t'es pris un arbre mais tu as parcouru {0} mètres de croissance !
 
Pour ton information, le Bus de l'Innovation a parcouru {1} mètres
de croissance depuis son départ.
 
Pour le faire redémarrer, appuie sur la cuisse de poulet du milieu.
La France compte sur toi !
'''
 
while 1:
 
    if interface.filtered_data(0) < seuil:
        position_bus += 1
 
    if interface.filtered_data(10) < seuil:
        position_bus -= 1
 
    # On met en place un moyen de reprendre le chemin de la croissance
    # si le bus de l'innovation s'est pris un arbre
    if if interface.filtered_data(5) < seuil and not le_bus_roule:
        le_bus_roule = True
        croissance_parcourue = 0
        position_chemin = init_position_chemin
        position_bus = init_position_bus
        compteur = 0
 
    if le_bus_roule:
 
        position_chemin += randint(-2, 2)
        position_chemin = sorted([1, position_chemin, position_max_chemin])[1]
 
        paysage = arbre * position_chemin
        paysage += chemin * largeur_chemin
        paysage += arbre * (largeur_ecran - len(paysage))     
 
        if position_bus <= position_chemin or position_bus >= position_chemin + largeur_chemin:
 
            bus = "\33[32mX\033[0m"
            le_bus_roule = False
 
        else:
            caractere = texte_du_bus[compteur%nb_caractere]
            bus = "\33[31m{0}\033[0m".format(caractere)
            compteur += 1
            # On incrémente la croissance parcourue à chaque tour
            croissance_parcourue += 5
 
        paysage = paysage[:position_bus] + bus + paysage[position_bus:]
        paysage = paysage.replace(arbre, arbre_classe_et_vert)
 
        print(paysage)
 
        if not le_bus_roule:
 
            # On calcule la croissance totale parcourue
            croissance_parcourue_totale += croissance_parcourue
            # On formate notre petit texte pour informer le joueur de sa 
            # performance individuelle et collective.
            print(texte_crash.format(croissance_parcourue, croissance_parcourue_totale))
 
        sleep(0.5)

bus_innovation_arcade

Le pattern strategy version gastronomique 9

vendredi 14 juillet 2017 à 21:11

Allez, un petit article de POO un peu avancée pour faire marcher ses neurones ce WE.

Le design pattern strategy, qui consiste à déléguer une partie du comportement d’un objet à un autre objet, est probablement l’un des motifs de conception les plus utiles en programmation. Trop souvent les gens utilisent l’héritage là où la composition serait plus adaptée, et une injection de dépendance bien faite permet de gagner beaucoup en qualité de code.

Si vous ne vous souvenez plus de ce qu’est le pattern strategy, vous pouvez faire un saut sur le chapitre qui en parle dans le guide de la POO :)

Mais comme un petit rappel ne fait pas de mal, en très court, strategy ressemble à ça :

class MonObjet:
    def __init__(self):
        self.strategie = MaStrategie()
 
    def foo(self):
        return self.strategie.foo()

Ce qui permet à une sous-classe de changer la strategy ou non :

class MonSousObjet(MonObjet):
   def __init__(self):
        self.strategie = MonAutreStrategie()

Ou de changer la strat dynamiquement :

hop = MonObjet()
 
hop.stategie = SuperNewStrat()

Mais si vous vous en tenez à ce design, les utilisateurs de la classe vont très vite rencontrer des limitations.

D’abord, une bonne stratégie peut avoir besoin de contexte. Dans ce cas, donnez lui le choix d’avoir une référence à l’objet parent:

class MonObjet:
    def __init__(self):
        # Passer self permet à la stratégie de connaître son contexte. 
        # Le désavantage est l'introduction potentiel d'un couplage entre 
        # les deux objets, et potentiellement des effets de bords supplémentaires. Cela reste 
        # néanmoins souvent une bonne idée.
        self.strategie = MaStrategie(self)   
    ...

Ensuite, une stratégie devrait pouvoir être passée à la création de l’objet :

class MonObjet:
    def __init__(self, strategie=MaStrategie):
        # On donne la priorité à l'objet passé en paramètre. Si il n'y en a 
        # pas on crée la stratégie par défaut.
        self.strategie = strategie(self)  
    ...

Cela permet d’overrider la stratégie pour les usages plus avancés, tout en permettant aux débutants de ne pas se soucier de cela car il existe quand même une valeur par défaut.

truc = MonObjet(UneStrategieDifferente)

Comme le travail dans un init est souvent assez redondant, avoir un endroit pour permettre aux sous-classes de facilement overrider la stratégie est une bonne pratique. En Python il est courant d’utiliser les variables de classes pour cela :

class MonObjet:
 
    # On appelle souvent cet attribut "strategy_class" ou "strategy_factory"
    strategie_par_default = MaStrategie
 
    def __init__(self, strategie=None):
        self.strategie = strategie(self) if strategie else self.strategie_par_default(self) 
    ...
 
class MonSousObjet(MonObjet):
    # Et boom, overriding de la stratégie par la classe enfant en une ligne.
    # Django fait ça par exemple avec les classes based views et l'attribut 
    # model
    strategie_par_default = MonAutreStrategie

Une fois que vous avez fait tout ça, vous avez déjà fait mieux que 90% des programmeurs. Néanmoins si vous voulez vraiment mettre la petit touche pro à votre API, vous pouvez aussi permettre la création dynamique de la stratégie:

class MonObjet:
 
    strategie_par_default = MaStrategie
 
    def __init__(self, strategie=None):
        self.strategie = strategie(self) if strategie else self.build_strategy() 
 
    def build_strategy(self):
        return self.strategie_par_default(self)
 
    ...

Wow, ça en fait des self et des factories :) En fait, ça fait la même chose qu’avant, c’est à dire que le tout premier exemple de code tout simple qu’on a vu en début d’article marche toujours ! C’est la beauté de la chose.

La différence, c’est que maintenant une classe enfant peut overrider build_strategy() et créer des stratégies à la volée, en fonction du contexte d’exécution. Par exemple créer une stratégie différente en fonction d’une valeur de base de données. C’est rare que ça arrive, et c’est vraiment de l’usage avancé. Mais quand vous avez ça, vous êtes certains que votre code est prêt à être utilisé par autrui. Car si cet autrui n’est pas content, il peut faire une profonde coloscopie à votre code et y insérer ce qu’il veut, quand il veut.

Être dev après tout, c’est être un peu poète.