PROJET AUTOBLOG


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

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

⇐ retour index

Travailler sur une lib externe à votre projet proprement en Python

lundi 6 octobre 2014 à 14:53

Quand on a une lib externe en dépendance à son projet, on veut être capable de l’importer MAIS pouvoir en modifier le code.

L’installer avec pip ou python setup.py install va copier le code dans le dossier site-packages et ce n’est pas ce que l’on veut car ça oblige à refaire l’installation à chaque modif.

Le mettre dans un dossier “libs” qu’on ajoute au PYTHON PATH ou pire, ajouter chaque dépendance au PYTHON PATH n’est pas une solution qu’on est fier d’exhiber au hackerspace du coin.

On s’en remet donc généralement à un symlink, sans savoir qu’il existe en fait un outil fait pour ça :

python setup.py develop

Cette commande va ajouter des entrées spéciales dans des fichiers placés dans site-packages qui vont vous permettre d’utiliser votre lib comme si elle était installée. Mais en vérité il va chercher le code dans votre dossier de dev, donc si vous modifiez le code, vous avez toujours la version de votre lib la plus fraîche.

Une fois qu’on a une lib stable, on peut retirer ce lien avec :

python setup.py develop --uninstall

Et installer la lib normalement.

Notez que tout ceci ne fonctionne que si le setup.py utilise setuptools et non distutils qui provoque l’erreur error: invalid command ‘develop’.

Comme setuptools inclut maintenant le meilleur de distutils, on peut remplacer :

from distutils.core import setup

Par :

from setuptools import setup

Sans soucis.

pip vient lui aussi avec un outil pour ça en la forme du flag -e qui fait exactement la même chose. Exemple :

pip install -e /chemin/local/vers/projet

Cela fonctionne comme pour python setup.py develop --uninstall mais on bénéficie de tous les goodies de pip en prime.

Néanmoins, pip pousse plus loin l’automatisation. Si vous faites pip install -e sur un repo distant, il va également cloner pour vous le code.

Ex :

pip install -e git+https://git@github.com/sametmax/minibelt.git#egg=minibelt

Et on retrouvera un clone du projet dans /chemin/vers/virtualenv/src/ qui sera importable, modifiable et pushable. Le résultat est automatisable, puisque pip freeze le prend en compte:

$ pip freeze
argparse==1.2.1
-e git+https://git@github.com/sametmax/minibelt.git@b898155b40d7de73cc404db7d274128f2b2fc330#egg=minibelt-master
wsgiref==0.1.2

L’URL est assez batarde à trouver par contre, car elle doit toujours finir par #egg=nom-du-projet et commencer par un double protocole, celui du VCS et celui du transport.

P.S: j’ai remis la coloration syntaxique et les iframes (donc la musique). J’aime bien ce thème là, mais la header chie sa mère. Est-ce que vous l’aimez suffisamment pour que je me casse le cul à le réparer ?

Trouver ce qui prend de la place en ligne de commande

lundi 29 septembre 2014 à 11:37

Windows a l’excellent WindDirStats, et Gnome a Baobab. Mais régulièrement je suis en SSH sur un server je lance df pour voir comment vont les disques. La vérité c’est que ceux avec un monitoring installés ne sont pas la majorité dans mes missions.

À un moment ou un autre, une partition est pleine. Et une fois qu’on a vidé /var/log et que le taux de remplissage ne semble pas baisser, il faut enquêter.

En général, je recherche sur le net une incantation magique du genre :

# trouver les fichiers qui prennent le plus de place
find . -type f -print0 | xargs -0 du | sort -n | tail -10 | cut -f2 | xargs -I{} du -sh {}
# trouver les dossiers qui prennent le plus de place
find . -type d -print0 | xargs -0 du | sort -n | tail -10 | cut -f2 | xargs -I{} du -sh {}

Puis je me souviens qu’il y a du, alors je commence à faire un truc comme ça :

du -a . | sort -n -r | head -n 10

Mais un jour je suis tombé sur un post d’un forum disant que je me cassais les couilles pour rien, et qu’utiliser ncdu était plus simple. Sous Ubuntu :

sudo apt-get install ncdu
ncdu

Et effectivement, je me cassais les couilles pour rien, c’est plus simple.

Accélérer les listings de l’admin Django avec beaucoup de ForeignKeys

dimanche 28 septembre 2014 à 09:32

Je pensais que ces astuces étaient très connues, mais quand j’en ai eu besoin, j’ai galéré pour mettre la main dessus. Du coup blogage, blogation, blogitude.

L’admin Django permet de faire automatiquement un listing des objets voulus afin de les modifier. Si un modèle a une ForeignKey et qu’on définit le champ en list_editable, Django va pondre un drop down pour choisir parmi les relations possibles.

Or, le framework fait une requête pour chaque objet de la liste. Si vous avez deux ForeignKeys sur votre modèle et 20 objets (valeur par défaut) dans la liste, ça vous fait donc 40 queries, juste pour afficher ces deux drop down. Doh.

On peut néanmoins forcer Django à cacher le résultat de la première requête, réduisant ainsi le compte à 1, avec cette étrange astuce d’une mère au foyer (consultants hate her !) :

class VotreClasseAdmin(admin.ModelAdmin)
 
    # Cette méthode est appelée pour créer le champ de formulaire de pour
    # chaque objet
    def formfield_for_dbfield(self, db_field, **kwargs):
 
        request = kwargs['request']
        formfield = super(ProductPageAdmin, self).formfield_for_dbfield(db_field, **kwargs)
 
        # Si le champ est editable dans la liste
        if db_field.name in self.list_editable and hasattr(formfield, 'choices'):
 
            # On tente de récupérer la query en cache
            cache_attr_name = '_%s_cache' % db_field.name
            choices_cache = getattr(request, cache_attr_name)
            if choices_cache is not None:
                formfield.choices = choices_cache
 
            # Pas de cache, on force Django à faire la query en accédant
            # au descripteur .choices et on met le resultat
            # en cache
            else:
                setattr(request, cache_attr_name, formfield.choices)
 
        # On retourne le champ de notre formulaire avec sa valeur mise
        # en cache
        return formfield

Malheureusement, il peut arriver qu’il y ait tellement d’objets que c’est votre navigateur qui panique. En effet, si vous avez un modèle Promotion avec un lien vers un modèle Produit et que vous avez 5000 produits en base, vous allez créer 20 <select> avec 5000 <options> dedans. 100000 balises dans une page, ça peut faire mal.

Dans ce cas, il vaut mieux désactiver la possibilité de faire un drop down, et mettre un champ text à la place dans lequel on entre un ID en utilisant :

class VotreClasseAdmin(admin.ModelAdmin)
 
     raw_id_fields = ('nom_de_votre_champ',)

Django n’est pas chien, et vous mettra un petit bouton en forme de loupe pour chercher l’ID dont vous avez besoin.

Si vous avez beaucoup de ForeignKey non éditables (readonly_fields), vous pouvez aussi vous fendre d’un select_related :

class VotreClasseAdmin(admin.ModelAdmin)
 
    def queryset(self, request):
        # On filtre le queryset que Django va utiliser pour populer la liste
        return super(MyAdmin, self).queryset(request).select_related('myfield')

Ça ne marche que sur les non éditables, car pour eux Django ne créé pas de champ de formulaire.

Passer d’un clé Putty (ppk) à une clé OpenSSH

samedi 27 septembre 2014 à 14:29

Cas d’école, mon client me donne la clé pour accéder à son instance Amazon (bouh !) et il me file une clé Putty puisqu’il est sous Windows.

Heureusement, Putty existe aussi sous nunux. Par exemple sous Ubuntu :

sudo apt-get install putty-tools

Et il embarque tout ce qu’il faut pour convertir sa clé :

puttygen cle.ppk -O public-openssh -o nouvelle_cle.pub
puttygen cle.ppk -O private-openssh -o nouvelle_cle

Y a plus qu’à mettre dans son dossier .ssh. En prime, je rajoute généralement ça dans .ssh/config :

Host ip ou domaine
HostName ip ou domaine
User username pour le server
IdentityFile ~/.ssh/nouvelle_cle

Comme ça pas besoin de sélectionner la clé manuellement à chaque connexion, si SSH voit cette IP, il me prend la bonne clé.

Mon dossier .ssh est un simple lien vers le vrai dossier dans la partition Truecrypt. Malgré la disparition du projet, j’ai pas trouvé mieux.

Multiboards a été migré

vendredi 26 septembre 2014 à 09:30

multiboards.net, la page Web qu’on trempe dans son café, a été migrée. Comme il n’y a aucune donnée associée, ben, le truc n’a pas bougé, dont vous le retrouverez tel qu’avant.

Plusieurs personnes nous ont demandé le code source. La raison pour laquelle il n’est pas publié, c’est que c’est un amas de code vraiment peu ragoutant, et qu’il faudrait vraiment le nettoyer pour éviter que la honte ne s’abatte sur nous.

Max voudrait en faire un truc personnalisable, avec des widgets, et tout, à la netwibes mais en plus simple. Je pense que ça n’arrivera jamais :)