Association du Grand Avignon des utilisateurs de Linux / *BSD, et de logiciels libres.

Mot-clé - Python

Fil des billets

vendredi 14 octobre 2016

Comment forcer urllib3 à vérifier les requêtes HTTPS

urllib3 est un module python extrêmement puissant, qui enrichit les différents modules relatifs aux réseaux présents dans la bibliothèque standard.

Il existe différentes manières pour effectuer une requête (il suffit de voir la documentation). Jusqu'ici je ne m'étais pas penché sur le cas du protocole HTTPS.

Par défaut on obtient ce message :

/usr/local/lib/python2.7/site-packages/urllib3/connectionpool.py:841: InsecureRequestWarning: Unverified HTTPS request is being made. Adding certificate verification is strongly advised. See: https://urllib3.readthedocs.io/en/l...

InsecureRequestWarning)

Même si l'on utilise la classe urllib3.connectionpool.HTTPSConnectionPool, le warning est toujours présent.

Il faut faire appel à un autre module, certifi, donc l'instance de HTTPSConnectionPool s'écrit alors :

[...]

conn = urllib3.connectionpool.HTTPSConnectionPool(host, cert_reqs='CERT_REQUIRED', ca_certs=certifi.where())
res = conn.request('GET', '/')

[...]

En annexe, vous trouverez un exemple complet.

On le lance de cette manière :

python npmjs.py
HTTPHeaderDict({'Content-Length': '3143', 'Via': '1.1 varnish', 'X-Cache': 'MISS', 'Accept-Ranges': 'bytes', 'X-Timer': 'S1476454061.911429,VS0,VE292', 'Vary': 'Accept-Encoding', 'X-Served-By': 'cache-fra1231-FRA', 'server': 'CouchDB/1.5.0 (Erlang OTP/R16B03)', 'Connection': 'keep-alive', 'etag': '"ETFO48QX32KIQMANPF4IXAOMS"', 'X-Cache-Hits': '0', 'Cache-Control': 'max-age=300', 'Date': 'Fri, 14 Oct 2016 14:07:42 GMT', 'Content-Type': 'application/json', 'Age': '0'})

samedi 12 septembre 2015

Un logiciel au code source ouvert c'est bien

Certains d'entre vous le savent peut-être, mais je suis un utilisateur heureux du bureau Xfce [1], je suis avec attention tout ce qui touche de près ou de loin à ce projet. Or des développeurs de la distribution Xubuntu ont développé un petit logiciel [2] permettant de sauvegarder la disposition du (ou des) panel(s). Il repose sur Gtk3 (grâce à la couche GObject Introspection) et Python3.

Avec la dernière version (1.0.1), des pré-réglages [3] sont déjà disponibles (je me tâte à les laisser dans le paquet pour FreeBSD), seulement quand on en sélectionne un, et par mégarde on clique sur le bouton de suppression on obtient ceci :

(Cliquez sur l'image pour la voir dans son format original)

xfpanel-switch-error.png

Je trouve que ce n'est pas élégant. J'ai donc proposé un patch qui vérifie si l'utilisateur est le propriétaire de l'archive. Si ce n'est pas le cas, une boîte de dialogue apparaît.

xfpanel-switch-rewrite-error.png

C'est mieux non ?

Notes

[1] Sous FreeBSD bien évidemment.

[2] Xfpanel-switch

[3] Pour Xubuntu et Debian

mercredi 16 avril 2014

Monitorer un média amovible sous FreeBSD ou DragonFlyBSD

Quant on est sous GNU/Linux, il existe udev, très largement utilisé sur ce système d'exploitation (SE), mais lorsque l'on utilise un système BSD, et en particulier FreeBSD il nous est impossible d'utiliser cette bibliothèque. Cependant les développeurs de FreeBSD ont développé un outil similaire devd(8).

Il est accessible via un socket unix.

J'ai voulu voir comment l'utiliser grâce aux systèmes de notifications du noyau kqueue(2)/kevent(2), avec le langage Python.

Je détaille un peu le script, tout d'abord nous allons initialiser un socket (le programme va fonctionner comme un client).

[...]
		s_file = os.path.join("/var", "run", "devd.pipe")

		# Create new socket object
		s = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
		s.connect(s_file)

		# Return the socket's file descriptor
		fd = s.fileno()

[...]

fd (file descriptor) est nécessaire pour kevent.

Les fonctions utilisées par kqueue/kevent sous Python sont accessible via le module select. Nous allons uniquement lire les données qui transitent par /var/run/devd.pipe.

Ci-dessous l'initialisation du mécanisme de notification.

[...]
				# Kernel queue object
				kq = select.kqueue()

				# Event to monitor (only attach)
				event = [select.kevent(fd, filter=select.KQ_FILTER_READ, flags=select.KQ_EV_ADD),]

				# Initialize kevent structure (like EV_SET macro in sys/event.h)
				ev_set = kq.control(event, 0, 0)
[...]

Nous pouvons « boucler » pour afficher les résultats quand un périphérique est branché. Un truc magique avec kqueue/kevent on a directement accès à la taille du tampon à lire.

[...]
						for event in events:
								# Display data from socket (event.data is size to read)
								print s.recv(event.data)
[...]

Voici le résultat lorsqu'une clé USB est branchée.

!system=DEVFS subsystem=CDEV type=CREATE cdev=usb/2.2.0
!system=DEVFS subsystem=CDEV type=CREATE cdev=ugen2.2

!system=DEVFS subsystem=CDEV type=CREATE cdev=usb/2.2.1
!system=DEVFS subsystem=CDEV type=CREATE cdev=usb/2.2.2

!system=USB subsystem=DEVICE type=ATTACH ugen=ugen2.2 cdev=ugen2.2 vendor=0x0930
 product=0x653d devclass=0x00 devsubclass=0x00 sernum="0B4085607142DAD4" release
=0x0100 mode=host port=6 parent=ugen2.1
!system=USB subsystem=INTERFACE type=ATTACH ugen=ugen2.2 cdev=ugen2.2 vendor=0x0
930 product=0x653d devclass=0x00 devsubclass=0x00 sernum="0B4085607142DAD4" rele
ase=0x0100 mode=host interface=0 endpoints=2 intclass=0x08 intsubclass=0x06 intp
rotocol=0x50
+umass0 at bus=1 hubaddr=6 port=2 devaddr=2 interface=0 vendor=0x0930 product=0x
653d devclass=0x00 devsubclass=0x00 sernum="0B4085607142DAD4" release=0x0100 mod
e=host intclass=0x08 intsubclass=0x06 intprotocol=0x50  on uhub2

!system=DEVFS subsystem=CDEV type=CREATE cdev=pass2

!system=DEVFS subsystem=CDEV type=CREATE cdev=da0

!system=DEVFS subsystem=CDEV type=CREATE cdev=da0s1

La dernière ligne est intéressante, car c'est le nom de la partition que l'on pourra « monter » sur le système.

lundi 12 août 2013

Aperçu du widget, GtkComboBox

Nous continuons notre série de billets consacrés aux principaux widgets sous Gtk.

Cette fois-ci, il s'agit de GtkComboBox, cet élément permet de créer une liste déroulante.

Lire la suite...

lundi 5 août 2013

Découverte du widget GtkEntry avec Python

Dans ce billet nous allons découvrir le widget, GtkEntry.

Cet élément graphique permet à un utilisateur de rentrer du texte (qui pourra, par la suite être traité).

Lire la suite...

mercredi 13 février 2013

Transformer des dates avec le module python-dateutil

Récemment, j'ai eu besoin de transformer des dates écrites dans ce format : Wed, 13 Feb 2013 05:34:15 +0100 en quelque chose de plus « normé », ISO 8601.

Lire la suite...

mardi 31 janvier 2012

Comment exclure un module avec setuptools ?

Pour ceux ou celles, qui maintiennent (ou on l'intention de créer) des paquets Python pour leur distribution favorite, je vous livre une astuce si vous voulez exclure un, ou plusieurs modules.

Dans mon cas, je ne voulais pas installer le dossier tests/ (il dépend bien souvent de la bibliothèque nose), lors de la création de mon package.

Nous allons utiliser la fonction find_packages() du module setuptools.

Voici ce que nous dit la docstring :

[...]

FUNCTIONS

find_packages(where='.', exclude=()) Return a list all Python packages found within directory 'where'

'where' should be supplied as a "cross-platform" (i.e. URL-style) path; it will be converted to the appropriate local path syntax. 'exclude' is a sequence of package names to exclude; '*' can be used as a wildcard in the names, such that 'foo.*' will exclude all subpackages of 'foo' (but not 'foo' itself).

[...]

La documentation :

[...]

find_packages() takes a source directory, and a list of package names or patterns to exclude. If omitted, the source directory defaults to the same directory as the setup script.

Exclusion patterns are package names, optionally including wildcards.

[...]

Un exemple va nous aider à bien comprendre (on se place dans les « mêmes conditions », qu'au moment de la création d'un paquet) :

olivier@bornem:~ $ tar -xzf /usr/ports/distfiles/waitress-0.8.tar.gz
olivier@bornem:~ $ cd waitress-0.8/
olivier@bornem:~/waitress-0.8 $ python
Python 2.7.2 (default, Jul  4 2011, 20:20:01) 
[GCC 4.2.1 20070719  [FreeBSD]] on freebsd8
Type "help", "copyright", "credits" or "license" for more information.
>>> from setuptools import find_packages
>>> l = find_packages(where='.')
>>> l
['waitress', 'waitress.tests', 'waitress.tests.fixtureapps']
>>> 

on obient une liste, de tous les dossiers contenant un fichier __init__.py.

Si l'on ne souhaite pas installer le répertoire waitress/tests, il faut le mentionner :

>>> l = find_packages(where='.', exclude=['waitress.tests'])
>>> l
['waitress', 'waitress.tests.fixtureapps']
>>> 

waitress/tests/fixtureapps/ est toujours présent (la compilation échouera, car le module tests sera absent). Il faut également le préciser tous les sous-dossiers

>>> l = find_packages(where='.', exclude=['waitress.tests', 'waitress.tests.fixtureapps'])
>>> l
['waitress']
>>> 

On peut utiliser un joker (ou wildcard).

>>> l = find_packages(where='.', exclude=['waitress.test*'])
>>> l
['waitress']
>>> 

Le plus gros du travail est fait, il ne reste plus qu'à rechercher un fichier MANIFEST.in, ou SOURCES.txt, et de supprimer les lignes correspondantes à ce module (on crée alors un patch).

Une dernière chose, la fonction find_packages() se trouve dans le fichier setup.py, on va également le patcher.

dimanche 29 janvier 2012

Exécuter une application WSGI avec systemd sous openSUSE

Ce billet est une « mise à jour » du précédent, concernant le déploiement de Mercurial, sous forme d'application WSGI.

Le fait de passer par le script /etc/init.d/after.local, pour lancer une telle application, ne m'a pas entièrement satisfait. C'est pourquoi j'ai décidé de me repencher sur ce point.

À la fin de l'article, j'évoqué, Gunicorn, comme serveur WSGI, en proposant même un exemple de fichier .service. Je me suis donc inspiré de celui-ci pour en créer un.

Le but c'est de pouvoir exécuter le script, hgweb.wsgi au démarrage.

Je vous propose donc, wsgi-hg.service. Il permet de lancer (ou d'arrêter) notre script WSGI. Il n'y a rien de particulier, à part la condition ConditionPathExistsGlob, qui me sert à tester si un fichier .wsgi (en réalité hgweb.wsgi) est présent sur le serveur, si c'est le cas, le service pourra être lancé.

Il faut bien sur, avoir correctement configuré son serveur Web. Par exemple pour Nginx :

[...]

    # Subdomain settings
    #
    # Mercurial
    #
    server {
	listen 80;
	server_name hg.errements.net;

	access_log /var/log/nginx/access-hg.log;

	location / {
		root /srv/www/htdocs/vhosts/hg;
		autoindex	off;

		proxy_path	http://127.0.0.1:8500;
		proxy_set_header	Host	$host;
	}
    }

[...]

Mais on peut aller encore plus loin, actuellement dans notre script wsgi, le socket réseau (le port, et l'adresse IP) sont codés en « dur ». On pourrait les passer en paramètre. Il faut pour cela utiliser le module argparse.

olivier@bornem:~ $ python hgweb-opts.wsgi -h                                 
usage: hgweb-opts.wsgi [-h] host port

positional arguments:
  host        Add IP address
  port        Add port number

optional arguments:
  -h, --help  show this help message and exit
olivier@bornem:~ $ 

On peut voir que deux paramètres sont obligatoires, l'ordre à une importance.

  • host, par exemple 127.0.0.1
  • port, par exemple 8500
olivier@bornem:~ $ python hgweb-opts.wsgi 127.0.0.1 8500                     
serving on http://127.0.0.1:8500

On peut maintenant adapter le fichier wsgi-hg.service, pour pouvoir passer ces paramètres à la ligne ExecStart.

Voici la ligne à copier.

[...]
ExecStart=/usr/bin/python2.7 /srv/www/htdocs/vhosts/hg/hgweb-opts.wsgi 127.0.0.1 8500
[...]

Pour lancer le service, on place ce fichier dans /etc/systemd/system/default.target.wants/ (ou /lib/systemd/system/).

root@bornem:~ # systemctl start wsgi-hg.service
root@bornem:~ # systemctl status wsgi-hg.service
wsgi-hg.service - Starts WSGI script (mercurial)
	  Loaded: loaded (/lib/systemd/system/wsgi-hg.service; disabled)
	  Active: active (running) since Sun, 29 Jan 2012 21:26:45 +0100; 38s ago
	 Process: 17745 ExecStartPre=/bin/echo Starting WSGI script for mercurial  (code=exited, status=0/SUCCESS)
	Main PID: 17747 (python2.7)
	  CGroup: name=systemd:/system/wsgi-hg.service
		  └ 17747 /usr/bin/python2.7 /srv/www/htdocs/vhosts/hg/hgweb...
root@bornem:~ # 

lundi 23 janvier 2012

Déployer Mercurial (hg) « derrière » un serveur Web (Nginx) sous openSUSE

Logos

Dans un précédent billet, j'avais montré comment l'on pouvait exécuter une application Web écrite dans le langage Python sans faire intervenir de serveurs Web.

Aujourd'hui, nous allons voir le cas, où un serveur (en l'occurence Nginx) est déjà en place.

En fait, le but inavoué de cet article est de comprendre le système d'init, systemd utilisé par openSUSE en autre.

Lire la suite...

mercredi 23 novembre 2011

Présentation du micro-framework Flask

logo framework Flask

Ce billet constitue une présentation du framework, Flask. Il permet de créer rapidement et très simplement des applications Web (blog, forum, etc.).

Par la suite d'autres billets seront publiés pour présenter d'une manière plus approfondi quelques unes de ses caractéristiques.

Lire la suite...

- page 1 de 2