When you get user information in console, you might, sometimes, need to get sensible information. Password for example.
Which can’t be displayed on the screen for security reasons.
The library Ruby Password allows you to do that quite easily.
However it implies you depend on this library. And that’s something I don’t wish. Particularly for something so simple.

The solution I’m suggesting here uses the linux features (not tested on windows. But who’s still using it today ? :mrgreen: ).

begin
    print "Username: "
    username = $stdin.gets.chomp

    print "Password: "
    # We hide the entered characters before to ask for the password
    system "stty -echo"
    password = $stdin.gets.chomp
    system "stty echo"
rescue NoMethodError, Interrupt
    # When the process is exited, we display the characters again
    # And we exit
    system "stty echo"
    exit
end

What are we doing ?
We start by asking the user’s nickname.

print "Username: "
username = $stdin.gets.chomp

This is not a sensible data and can be displayed. Nothing specific to do.

Then we ask for a password. Here we must hide it.

print "Password: "
system "stty -echo"
password = $stdin.gets.chomp
system "stty echo"

The « stty -echo » will hide every character that should be displayed on the console.
The « stty echo » displays them again.

Until there is works. Cool !
But somehowe we have a boring user, whom decides at the last moment to enter Ctrl-C to quit the program and finds himself in console with the -echo mode and doesn’t see what he enters in. We’ve just lost a friend.

Fortunately we have exceptions notifications and we already detect an Interrupt to exit the program cleanly.
Then we just have to display the characters again when there’s this interrupt :)

begin
    # ...
rescue NoMethodError, Interrupt
    system "stty echo"
    exit
end

Hop ! :)
And the project that uses this is glynn :)

Lorsque vous manipulez un repository GIT en utilisant (voir en abusant (ce qui n’est pas forcément négatif)) les branches, vous pouvez régulièrement vous poser la question « dans quelle branche suis-je ? Est-ce la bonne ? »
Et c’est toujours particulièrement lourd de devoir faire un
git branch

Afin de voir toutes les branches et de trouver l’active.
Je viens cependant de tomber sur une astuce donnée par le support github.

# git branch
parse_git_branch() {
    git branch 2> /dev/null | sed -e '/^[^*]/d' -e 's/* \(.*\)/(\1) /'
}
PS1="\$(parse_git_branch)$PS1"

Placez ceci dans ~/.bashrc ou /etc/bashrc (pour que cela soit valide pour tous les utilisateurs de la machine).
Rechargez votre console et admirez :)

dmathieu@dmathieu-ubuntu:~$ cd /home/dmathieu/projects/refstats/
(master) dmathieu@dmathieu-ubuntu:~/projects/refstats$

Lorsque vous êtes dans un repository GIT, la branche courante s’affichera.
Dans le cas contraire, rien ne s’affichera :)

Vous avez normalement déjà manipulé les commandes console de Django, accessibles via manage.py.
./manage.py runserver

Cependant il peut être utile, dans plus d’une application, d’avoir des méthodes console pour lesquelles vous désirez obtenir l’environnement web, mais en console.
Pour charger des données depuis un flux XML par exemple. Ou encore vider une base de données.
Ainsi, vous pourrez faire :

./manage.py votre_commande

Dans l’application de votre choix, et qui doit être présente dans le INSTALLED_APPS de settings.py, créez l’arborescence suivante :
- management
|- __init__.py
|- commands
|– __init__.py

Ainsi, vous aurez ceci :
- votre_application
|- management
|– __init__.py
|– commands
|— __init__.py

Puis créez un fichier, que vous nommerez comme votre nouvelle commande dans le dossier commands.
Par exemple export.py

Dans ce fichier, vous placerez le code suivant :
from django.core.management.base import NoArgsCommand
class Command(NoArgsCommand):
  help = "Message d'aide concernant votre commande"
  def handle_noargs(self, **options):
    # Le contenu de votre commande
    print("Hello World")

Si, maintenant, vous tapez dans une console :

./manage.py export

Et le code présent dans votre méthode handle_noargs() sera exécuté :)

De la même manière que en Ruby, Django propose une solution d’envoi d’email.
Mais toute application Python n’utilise pas forcément Django. Et il peut arriver d’avoir besoin d’envoyer un email sans Django.

C’est ce que j’ai fait en développant l’outil de rapport de positions par email de RefStats.

Pour cela, nous allons utiliser la librairie smtplib.
Commençons par importer cette librairie.
import smtplib
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText

Puis envoyons notre email.
msg = MIMEMultipart('alternative')
msg['Subject'] = 'Sujet de l\'email'
msg.attach(MIMEText('contenu texte', 'text'))
msg.attach(MIMEText('contenu html', 'html'))
email = smtplib.SMTP()
email.connect('localhost')
# email d'envoi - email de réception - message
email.sendmail('noreply@dmathieu.com', 'you@example.org', msg.as_string())
email.close()

Nous instancions l’email, y définissions son sujet.
Ainsi que du contenu html et du contenu texte.
Puis nous nous connectons au serveur smtp (ici localhost) et envoyons l’email.

Si vous avez déjà essayé d’envoyer un email avec rails, vous avez constaté que c’est articulièrement aisé.
Mais ruby ce n’est pas que du rails !
Dans le cas du redéveloppement de Refstats par exemple, j’ai recodé le crawler de celui-ci, qui va récupérer de manière journalière les positions de chacun de vos sites.
Et je désire être rapidement être mis au courant si j’ai une erreur qui est apparue afin de pouvoir la corriger tout aussi vite.

Du coup si je soulève une exception, je veux m’envoyer un email.
Bien évidemment, je n’ai qu’une application console.
Pas de rails derrière, bien que j’utilise Active Record.

Du coup pas d’action mailer. Et pas de fonction « mail » comme en PHP.

Il est cependant assez aisé d’envoyer un email :
require 'net/smtp'
def send_email(from, to, subject, message)
  msg = "Subject: " + subject + "\r\n\r\n" + message
  Net::SMTP.start('localhost') do |smtp|
    smtp.send_message msg, from, to
  end
end

Nous déclarons une méthode send_email, qui prends les paramètres :
email de l’envoyeur; email du destinataire; sujet de l’email et son message.

Nous créons l’entête du message avec son sujet.
Puis nou instancions un Net::SMTP avec l’adresse du serveur SMTP (et en second paramètre son port si autre que 25).
Et on envoie notre message !
Pour plus de détails, notamment l’identification, je vous invite à vous référer à la documentation de Net::SMTP.

Comme j’en ai déjà parlé récemment, Rails permets, depuis sa version 2.2, de gérer les sites multilingues.
Du coup comme j’avais envie de m’amuser, j’ai fait une mini application console qui permet de prendre un fichier yaml de langue, le traduit dans la langue de votre choix (en utilisant Google Translate) et écrit les nouvelles données dans un second fichier. Cela s’appelle Translator.

Pour l’utiliser, c’est très simple. En ayant ruby et rubygems d’installé, il vous manque encore deux gem :
gem install yaml googletranslate
Le premier permet de parser des documents YAML. Le second est une librairie permettant de faire des appels à l’API Google Translate.

Puis ouvrez une fenêtre console, rendez-vous dans le répertoire de translator et tapez :
ruby translator.rb /chemin/vers/le/fichier/originel.yml /chemin/vers/le/nouveau/fichier.yml langue
Exemple :
ruby translator.rb en.yml fr.yml fr
Traduira le document en.yml de la langue qui lui est définie vers le français en mettant le contenu dans fr.yml.

Ruby est très développé et très bien document lorsqu’il s’agit de développer des applications web.
Mais parce qu’il n’y a pas que le web dans la vie (ah bon ???), il peut être utile, même dans le cas du développement web, de mettre en place des applications console.

Par console, j’entends sans aucune interface graphique. Celles-ci sont encore un autre sujet.

Du coup en faisant quelques recherches, j’ai découvert SimpleConsole, qui est justement un framework de développement d’applications console simples.
Et en plus il gère un (semblant) de MVC.

Votre application va donc se diviser en deux parties.
Supposons un fichier « myapp.rb », avec le code suivant :
#!/usr/bin/env ruby -w
require 'rubygems'
require 'simpleconsole'
require 'views/myapp'

class Controller < SimpleConsole::Controller
  params :string => {:n => :name, :w => :word}

  def default
    @name = params[:name]
    @word = params[:word]
  end
end

SimpleConsole::Application.run(ARGV, Controller, View)

Puis un fichier views/myapp.rb
class View < SimpleConsole::View
  def default
    puts "Your name is " + @name + "."
    puts "You wanted me to say the word " + @word + "."
  end
end

Si vous exécutez
ruby myapp.rb -name Damien -w Yay

La console vous retournera alors :

Your name is Damien.
You wanted me to say the word Yay.

Le code est tout d'abord interprété par le contrôleur pour ensuite être transmis à la vue, qui renvoie le contenu que vous désirez.
C'est du pseudo MVC et la chose serait largement améliorable.

Mais c'est un bon début pour une application console qui se doit d'être simple.
Et puis vu que l'application ne semble plus maintenue, il est possible que je la forke et que je fasse quelques commits dessus ;)

CakePHP fournit de base quelques méthodes permettant de développer des applications dans le but de les exécuter avec PHP-cli, c’est à dire de les exécuter comme des scripts shell au lieu de passer par l’interface graphique.

Je ne propose pas ici un tutoriel permettant de développer ce genre de scripts. Il en existe déjà un résumant assez bien la chose sur cakebaker (en).

Après avoir développé une application, nous avons plusieurs tâches qui sont exécutées dans le script shell principal.

Cependant il peut être utile, pour diverses raisons de tests, d’analyses de bugs voir statistiques, d’exécuter les mêmes méthodes présentes dans nos tasks mais via une page web.

Il serait fortement bête de devoir faire un copier/coller de notre méthode et de la remettre dans un contrôleur. Cela ne serait pas vraiment en concordance avec le mojo du framework (« think twice, code once« ).

Supposons donc que dans votre contrôleur « admin », vous désiriez utiliser la méthode « makeTest » de la tâche « test ».
Créez une nouvelle action dans votre contrôleur.

Dans celle-ci, placez les lignes suivantes :

include(APP.'console/libs/shell.php');
vendor('shells/tasks/test');

Vous avez ici inclu dans votre action les fichiers nécessaires l’instanciation de votre tâche.

Le premier fichier contient la classe parente à celle que doit avoir votre tâche. La seconde contient votre tâche (remplacer « test » par le nom de votre tâche).

$tache = $test->makeTest();

Maintenant initialisons notre tâche :

$test = new TestTask();

Et exécutons la méthode que nous désirons pour notre tâche.

$tache = $text->makeTest();

Vous n’avez maintenant plus qu’à effectuer l’action que vous désirez avec les données que votre méthode vous renvoie.

Irish Coffee

 
Fork me on GitHub