Planète AFPy RSS

[AFPy-Nantes] Meetup Python du 23 décembre : boire un verre !

Publié le 2014-12-19 23:00:00

Ce mardi 23 décembre, nous proposons au pythonistas de Nantes de se retrouver pour prendre un verre.

Le rendez-vous est à 19h au Delirium Tremens, 19 allée Baco à Nantes.

Certains seront absents, le système de distribution du Père Noël semble-t'il repose sur Python (ce qui explique peut-être qu'il dépasse celui d'Amazon écrit en Perl !).

Joyeuses fêtes !

[afpyro] AFPyro à Lyon - mardi 16 décembre

Publié le 2014-12-16 00:00:00

Un Afpyro aura lieu le mardi 16 décembre à partir de 20h à l’Antre Autre - 11 rue Terme - 69001 Lyon.

Une présentation sur Sentry sera donnée. Sentry est un logiciel permettant de suivre les erreurs pouvant se produire dans vos applications.

L’Antre Autre est un lieu où nous pouvons discuter autour d’un verre, et, pour ceux qui le souhaitent, prendre un repas.

Pour se rendre à l’Antre Autre :

  • en métro : arrêt Hôtel de Ville
  • en bus : lignes C13 et C18 arrêt Mairie du 1er ou lignes 19, C14 et C3 à l’arrêt Terreaux
  • en vélo’v : stations Place Sathonay, Carmélites Burdeau, Place de la paix

[logilab] Generate stats from your SaltStack infrastructure

Publié le 2014-12-15 15:52:00

As presented at the November french meetup of saltstack users, we've published code to generate some statistics about a salstack infrastructure. We're using it, for the moment, to identify which parts of our infrastructure need attention. One of the tools we're using to monitor this distance is munin.

You can grab the code at bitbucket salt-highstate-stats, fork it, post issues, discuss it on the mailing lists.

If you're french speaking, you can also read the slides of the above presentation (mirrored on slideshare).

Hope you find it useful.

[sciunto] Champ de vitesse dans une mousse

Publié le 2014-12-13 23:00:00

J'ai récemment écrit un petit guide sur le tracking de bulles dans une mousse. A défaut de temps, voici donc un billet court plutôt que rien afin de référencer cette contribution. J'ai utilisé la bibliothèque Trackpy écrite en Python afin de tracker les bulles. Cependant, une étape supplémentaire d'identification a été nécessaire (car en dehors des clous des particules plus classiques) et j'ai utilisé scikit-image.

Le tuto a ainsi pour ambition de montrer la versatilité de trackpy pour des objets moins conventionnels. Il est disponible ici.

[Biologeek] Lean et favelas

Publié le 2014-12-12 11:00:00

Autre exemple : observez Lean startup, une approche extrêmement puissante pour construire rapidement un produit/service en itérant directement avec ses utilisateurs. Si vous deviez construire un quartier en mode Lean, vous commenceriez par construire rapidement des logements répondant aux besoins minimum exprimés par les utilisateurs : un sol, des murs, un toit et une porte pour assurer le clos et le couvert du logement. La condition minimum de l’habitat est respectée. Par contre si vous produisez ça à l’échelle du quartier vous avez construit une favela.

En voulant répondre rapidement au besoin minimum de l’utilisateur vous avez livré un produit qui générera rapidement des problèmes de salubrité, de promiscuité, et de violence. Finalement vous avez bien suivi la méthode mais la qualité de vie (ou l’expérience utilisateur) n’est pas satisfaisante.

Dans cet exemple la production s’est attachée à répondre aux besoins conscients de l’utilisateur. Les besoins futurs, non-conscients et non-exprimés, comme une bonne qualité de vie, la sécurité ou la salubrité, n’ont pas été pris en considération. Ils conditionnent pourtant largement la qualité de l’expérience utilisateur.

En Lean comme ailleurs l’expert est aussi là pour, si j’ose dire, préserver l’utilisateur de lui-même. Si l’utilisateur est conscient de ses besoins présents, est-il conscient des conséquences futures de ces choix ? On peut en douter…

Non, la conception centrée utilisateur doit être encadrée par des ressources responsables de la vision du projet. Il faut des visionnaires, il faut des innovateurs, des planificateurs. Il faut des garants de la qualité du produit/service pas seulement pour l’usage présent, mais aussi pour les usages futurs.

Cette empathie dont on pâtit

Il y a 2 choses qui me gênent dans cet extrait :

  • la première de penser que la démarche Lean aboutira à la construction d’une favela ;
  • la seconde d’avoir l’arrogance de croire que l’expert est un visionnaire qui connait mieux le problème que ceux qui le vivent.

Si je reprends l’exemple de l’habitat, la première itération débouchera en effet peut-être sur une cabane. Puis la seconde, une fois que des personnes y auront vécu, débouchera sur un groupe de cabanes avec une pièce commune et des sanitaires externes. Puis la troisième pourrait être à l’origine d’un renforcement des murs existants et la construction d’une école. Enfin lors de la quatrième on démolirait la pièce commune pour faire une salle des fêtes en béton. Ou tout autre chose en fonction des besoins des personnes qui sont concernées au quotidien. Lean n’est pas fait pour développer un prototype et passer à l’échelle à partir de celui-ci mais bien pour itérer sur ce prototype de manière à ce qu’il acquiert le maximum de valeur avant de passer à l’échelle. Si personne ne souhaite vivre dans une favela, un projet Lean ne devrait jamais aboutir à une favela (au passage comparer une n-ième fois le développement logiciel à du BTP est délirant).

Passons à l’encadrement des utilisateurs trop stupides pour pouvoir avoir une vision de leur produit. Dans un système complexe, l’expert et l’utilisateur sont sur un pied d’égalité vis-à-vis de la prédiction qu’ils peuvent faire sur un produit innovant : c’est entre la voyance et le bullshit. Personne ne peut anticiper dans un tel système. La chance de notre domaine c’est la flexibilité que l’on a pour pouvoir s’adapter au changement. L’agilité propose des outils pour que les compétences de l’expert (estimation relative de la complexité et qualité interne) et l’utilisateur (priorité et budget) puissent travailler ensemble afin de maximiser la valeur de chaque itération. Inutile d’anticiper (faussement) sur les usages futurs si l’on est suffisamment réactif dans les développements présents. L’enjeu est de rester suffisamment réactif tout au long du processus, à la fois techniquement mais aussi en terme de retours utilisateurs.

Je fais rarement de la pub par ici mais la formation qu’expérimente Stéphane dans le domaine est vraiment éclairante.

[AFPy Salt-fr] Compte rendu Salt Meetup Paris - novembre 2014

Publié le 2014-12-10 23:00:00

La communauté Salt s'est a nouveau réunie pour son meetup bi-mestriel autour de trois présentations. Voici un compte rendu (très court) pour vous renvoyer vers les références.

Utilisation de salt pour gérer des machines desktop sous windows et mac os.

Aurélien Minet de l'ENS Cachan nous a présenté son utilisation de salt dans la gestion de postes utilisateurs OS X et Windows.

Support de présentation à venir.

Création de statistiques pour une infrastructure salt

Arthur Lutz de Logilab nous a présenté un développement pour évaluer la distance entre l'état souhaité de son infrastructure salt et l'état réel.

Arthur Lutz

SaltPad

Boris Feld

Boris Feld de tinyclues nous a présenté une interface web pour piloter salt.

Conclusion

Merci à tinyclues d'avoir acceuilli et apporté à boire, ainsi qu'à Logilab pour les pizzas.

Pour le prochain meetup (en janvier), votez pour une date sur framadate et n'hésitez pas à inscrire une proposition de présentation ou de lieu sur le pad d'organisation.

[Biologeek] Cours IUT : Évaluation et Bilan

Publié le 2014-12-09 11:00:00

Supprimer les notes, c’est assurément une façon de se recentrer sur l’apprentissage ; c’est arrêter de chiffrer quelque chose qui n’est pas chiffrable. Mais, arrêter la note ne veut pas dire arrêter d’évaluer, car, bien évidemment, l’étudiant a besoin de repères, de savoir où il en est. Quand il n’y arrive pas, il le sait : il n’a pas besoin de recevoir une mauvaise note. Il faut trouver comment stimuler son envie de continuer à apprendre, alors que la mauvaise note, en général, lui donne envie de ne plus essayer. La note, pour les bons élèves, sert de carotte : elle est intéressante en terme d’émulation. Mais il faut trouver une autre façon de stimuler l’apprentissage : en disant à la personne que ce qu’elle fait est bien, qu’elle peut être fière d’elle. Si l’enthousiasme est réveillé, elle aura envie de continuer à apprendre.

Isabelle Peloux : Passer de la note à l’évaluation

Je suis contre le système de notation actuel. Mais il faut pourtant que j’attribue une note à chaque élève. Alors je vais essayer de transformer cela en auto-évaluation. À partir d’un exercice imposé sur une heure, seuls (mais connectés) face à la page blanche, essayer de produire quelque chose à partir des concepts que j’ai essayé de leur transmettre. Au final l’évaluation sera davantage intéressante pour moi. Qu’ont-ils retenu de ces 24 heures passées ensemble ? Un peu, beaucoup, rien du tout ?

Le débriefing/correction sera l’occasion de faire un bilan de ce que l’on a abordé ensemble. D’analyser ce qu’il manque à ce cours pour être plus pertinent et plus engageant. De vérifier qu’il a répondu à leurs craintes initiales. Mon bilan personnel est assez mitigé :

  • la responsable de la promotion est très réactive et compréhensive mais le service technique de la fac est clairement en position de « difficultateur » ;
  • j’ai pris du plaisir à transmettre des concepts aux élèves mais cela manque cruellement de recul sur la profession ;
  • les étudiants sont demandeurs mais il faut que ça reste dans le cadre de leurs heures de cours ;
  • le fil rouge du cours (projet personnel) est motivant mais manque de finitions faute de temps.

Malgré ces retenues, le bilan est globalement positif et j’espère pouvoir participer par la suite plus en amont pour orienter le programme afin qu’il réponde un peu mieux aux enjeux et pratiques du métier.

C’est en observant nos deux apprentis tantôt réussir, tantôt échouer, que je fus soudain prise d’empathie. J’ai repensé à mes propres débuts.

J’ai alors eu envie de les aider. Au quotidien, j’essaie de les aider du mieux que je peux, bien que cette aide ne soit pas toujours facile à caser dans un rythme de production soutenu.

C’est pourquoi je publie ici les 24 conseils que j’aurais voulu qu’on me donne aussi quand j’ai débuté, afin que cela puisse servir à d’autres débutants… quitte à prendre moi-même un petit coup de vieux !

24 conseils que j’aurais voulu que l’on me donne quand j’ai débuté

Quelques conseils que j’aimerais leur donner pour la suite :

  • Ce que vous avez appris aujourd’hui sera faux demain. Vous devez continuer à expérimenter par vous-même et pratiquer une veille au quotidien ;
  • Validez vos acquis par la transmission. Je n’ai jamais autant appris qu’en essayant de partager le peu que je savais déjà sur le sujet ;
  • Publiez votre travail. Même si ça vous semble parfois dérisoire, racontez le processus qui vous a permis d’arriver à ce résultat ;
  • Rencontrez vos pairs. Rencontrez vos interlocuteurs. Rencontrez vos utilisateurs.

[carlchenet] Site comme Hacker News en français : Le Journal Du Pirate

Publié le 2014-12-08 23:00:41
Suivez-moi aussi sur Identi.ca  ou Twitter  ou Diaspora* Avant tout l’adresse du site : Le Journal Du Pirate https://infos.mytux.fr Un site web comme Hacker News mais francophone propulsé par un Logiciel Libre, je trouve que ça manquait à la communauté francophone. C’est maintenant chose faite avec un site dérivé du moteur de Lobste.rs. Les sources…

[Biologeek] Cours IUT : PHP et Formulaires

Publié le 2014-12-07 11:00:00

A l’origine d’internet il existait une personne qui possédait tous les pouvoirs. Cet individu avait le droit de vie ou de mort sur un site internet. Cette personne c’était le maître du web aka webmaster.

Il connaissait tous les raccourcis Frontpage, pouvait animer une page à l’aide d’images 16 couleurs en .gif, faire défiler ou clignoter du texte, et transférer ses fichier sur le web à l’aide de logiciels FTP.

Certains de ces individus se sont transformés en développeurs web. D’autres en découpeurs HTML, encore appelés intégrateurs. Ces magiciens du CSS étaient capables de cacher des liens dans des images à l’aide de leur logiciel de prédilection Dreamweaver. Ils ont aussi découvert le copier / coller et l’utilisaient à travers le web pour récupérer du code source JavaScript.

Mais ce temps est révolu...

Manifeste d’un développeur front-end éclairé

J’ai été contraint et forcé de parler de PHP. Un langage que je n’ai pas utilisé depuis 10 ans. Un langage de bidouilles par excellence. Un langage dont la qualité des ressources en ligne est très variable (mais il y a des pépites). Dur.

Mais c’est aussi l’occasion d’essayer de transmettre quelque chose que je ne maîtrise pas du tout, entamer la discussion sur l’importance d’apprendre à apprendre tout au long de sa carrière. Sur ce que l’on peut apprendre en aidant sur un forum, sur irc, en participant à une conférence ou en formant. Et de faire une introduction à la mise en forme des formulaires et aux attributs HTML 5 dédiés. Et de troller un peu aussi hein.

Je compte partir sur un formulaire d’envoi d’email très basique mais qui permet d’explorer les différents concepts (architecture client/serveur, double validation, séparation du code et de l’affichage, etc) :

Ce simple exemple nous prendra je l’espère moins de 4 heures à expliquer, c’est pas gagné car à 24 l’inertie de compréhension est terrible. Il faut que j’arrive à mieux faire en sorte que ceux qui percutent rapidement aident les autres.

Pour l’instant, les retours sur les cours sont vraiment positifs et les étudiants en redemandent ce qui est très motivant. Je vais peut-être avoir une autre classe plus technique pour parler du web mobile (whatever it means) lors du premier trimestre 2015.

[tarek] 5 work week tips

Publié le 2014-12-06 07:05:00

Our Mozilla work week just ended with an amazing evening. We had a private Mackelmore concert. Just check out Twitter with the #mozlandia tag and feel the vibe. example.

When they got on stage I must admit I did not know who Mackelmore was. yeah sorry. I live in a Spotify-curated music world and I have no TV.

At some point they played a song that got me thinking: ooohhh yeah that song, ok.

Anyways.

During some conversations a lot of folks told me that they where overwhelmed by the work week and har a very hard time to keep up with all the events. Some of them were very frustrated and felt like they were completely disconnected.

I went through this a lot in the past but things improved throughout the years. This blog post collect a few tips.

1. List the folks you want to meet

This one is a given. Before you arrive, make a list of the folks you want to meet and the topics you want to talk about with them.

Make that list short. 10, no more.

2. Do not code

This is the worst thing to do: dive into your laptop and code. It's easy to do and time will fly by once you've started to code. People that don't know you well will be afraid of disturbing you.

Coding is not something to do during your work weeks. If you need a break from the crowd that's the next tip.

3. Listen to your body

A work week is intense for your body. By the end of the week you will look like a Zombie and you will not be able to fully enjoy what's happening. If you are coming for a far place, the jetlag is going to make the problem worse. If you're a partygoer that's not going to help either. All the food and drinks are not really helping.

I've seen numerous folks getting really sick on day 3 or 4 because they had intensive days at the beginning of the event. It's hard not to burn out.

Some (young) folks are doing fine on this. I know I am not. What I did for the Portland work week was to skip everything on day 2 starting at 5pm, ate a soup and went to sleep at 8pm. Skipping on all the cookies and beers and goodies gives your body a bit of rest :)

That gave me the energy I needed for day 3.

4. Don't hang with your team all the time

You talk to those folks all the time. Meet other folks, check out other sessions, etc.

This is especially important if your native langage is not English. I got trapped many time by this problem: just hanging with a few french guys.

5. Walk away from meetings

Don't be shy of walking away from meetings that don't bring you any value. Walk out discretly and politely. You are not in a meeting to read hackernews on your laptop. You can do this at home.

People won't get offended in the context of a work week - unless this is a vital team meeting or something.

What are your tips?

[tarek] DNS-Based soft releases

Publié le 2014-12-06 05:30:00

Firefox Hello is this cool WebRTC app we've landed in Firefox to let you video chat with friends. You should try it, it's amazing.

My team was in charge of the server side of this project - which consists of a few APIs that keep track of some session information like the list of the rooms and such things.

The project was not hard to scale since the real work is done in the background by Tokbox - who provide all the firewall traversal infrastructure. If you are curious about the reasons we need all those server-side bits for a peer-2-peer technology, this article is great to get the whole picture: http://www.html5rocks.com/en/tutorials/webrtc/infrastructure/

One thing we wanted to avoid is a huge peak of load on our servers on Firefox release day. While we've done a lot of load testing, there are so many interacting services that it's quite hard to be 100% confident. Potentially going from 0 to millions of users in a single day is... scary ? :)

So right now only 10% of our user base sees the Hello button. You can bypass this by tweaking a few prefs, as explained in many places on the web.

This percent is going to be gradually increased so our whole user base can use Hello.

How does it work ?

When you start Firefox, a random number is generated. Then Firefox ask our service for another number. If the generated number is inferior to the number sent by the server, the Hello button is displayed. If is superior, the button is hidden.

Adam Roach proposed to set up an HTTP endpoint on our server to send back the number and after a team meeting I suggested to use a DNS lookup instead.

The reason I wanted to use a DNS server was to rely on a system that's highly available and freaking fast. On the server side all we had to do is to add a new DNS entry and let Firefox do a DNS lookup - yeah you can do DNS lookups in Javascript as long as you are within Gecko.

Due to a DNS limitation we had to move from a TXT field to an A field - which returns an IP field. But converting IP to integer values is not a problem, so that worked out.

See https://wiki.mozilla.org/Loop/Load_Handling#Service_Soft_Start for all the details.

Generalizing the idea

I think using DNS as a distributed database for simple values like this is an awesome idea. I am happy I thought of this one :)

Based on the same technique, you can also set up some A/B testing based on the DNS server ability to send back a different value depending on things like a user location for example.

For example, we could activate a feature in Firefox only for people in Connecticut, or France or Europe.

We had a work week in Portland and we started to brainstorm on how such a service could look like, and if it would be practical from a client-side point of view.

The general feedback I had so far on this is: Hell yeah we want this!

To be continued...

[AFPy-Nantes] Compte-rendu des conférences : Pélican et (i)Python

Publié le 2014-12-03 23:00:00

Un meetup tardif, dû à la PyConFr, centré sur deux présentations opposées en termes de technicité : une présentation d’un outil (presque) clés-en-mains, et un survol des possibilités de iPython dans la dataviz cartographique, ainsi que quelques bibliothèques utiles.

Pelican : le futur du web vintage

Intervenant : Damien Nicolas, Gordon

Principe

Pelican est un générateur de site statique écrit en Python initialement par Alexis Métaireau.

Le site est réalisé via un langage de template ensuite traduit en HTML. Le contenu généré peut ensuite être déployé sur un serveur sans configuration supplémentaire. Il n’y a donc pas d’applicatif sur le serveur.

Les avantages d’un tel système sont nombreux. D’abord la simplicité. Un simple éditeur de texte suffit pour écrire le contenu. Étant purement textuel, le contenu est facilement versionnable et recevoir/fournir un patch peut se résumer à un envoi de mail. L'absence d’applicatif côté serveur rend la configuration serveur aisée et la sécurité proche de la perfection : pas d’applicatif = pas de faille.

Bon évidemment, il y a quelques inconvénients. En terme de fonctionnalité d’abord, l’absence native de recherche ou de commentaire. Mais heureusement, il est possible via des extensions de remédier à ces problèmes. En revanche, la barrière à l’entrée est immuable. Pour faire du Pelican, il faut pouvoir écrire du RestructuredText ou du Markdown. Pour profiter pleinement de tout ça, il est bon de savoir invoquer une commande “make” ou “git push”. Plus que rébarbatif pour un néophyte.

En pratique

L’installation se fait comme n’importe quelle bibliothèque Python. On crée un environnement virtuel (e.g. via pyvenv en Python 3). On l’active et via pip on peut installer Pelican. A noter que par défaut, Pelican supporte uniquement le RestructuredText pour les articles, pour markdown, il faudra installer le paquet markdown en plus. On peut ensuite préparer le site via l'installer de Pelican, qui de façon interactive pose quelques questions qui facilitent grandement la configuration. A cette étape, on paramètre notamment les différents moyens utiliser pour déployer le site web sur le serveur.

Une fois configuré, on peut écrire des articles. Ces derniers pourront être placés dans un dossier articles dans le dossier content (tout ceci est paramétrable). Pour générer le site, le plus simple est d'utiliser la commande make :

make html

Et on déploie :

make upload

Et la magie opère. Le site est redéployé !

Il est assez facile de tester localement, Pelican permet d’utiliser un simple serveur HTTP en local pour vérifier ses modifications avant de publier des erreurs ;).

Extensions

On l’a écrit, nativement, il n’existe pas de gestion des commentaires ni de fonction de recherche. Rien d’insurmontable cependant.

Commentaires

Pour les commentaires, une solution simple est d’intégrer Disqus. Disqus est un service permettant de stoquer des commentaires sur un autre serveur que celui de l’application. L’extension disqus_static permet d’utiliser l’API de ce service pour gérer les commentaires dans Pelican. Il y a d’autres alternatives, comme par exemple gérer des commentaires statiquement dans des fichiers sur le serveur hébergeant Pelican. Cette dernière solution permet d’éviter les dépendances à un service tiers.

Recherche

Ici, on pourra fait appel à tipue_search, qui permet d’intégrer une fonctionnalité de recherche côté client. Sur le serveur, un fichier JSON est généré. Celui-ci est ensuite utilisé côté client pour de la recherche via JQuery. Le thème elegant intègre cette fonctionnalité nativement.

Autres extensions

Très extensible, il est possible de faire tout un tas de choses avec Pelican. C’est d’ailleurs le moteur utilisé pour le blog que vous lisez en ce moment. Pour vous faire une idée des possibilités, c’est par là : <https://github.com/Python-Nairobi/pelican-plugins>`_.

Les slides de la présentation sont disponibles ici : Pelican

Dataviz avec iPython

Intervenant : Thomas Gratier

IPython est un shell Python interactif offrant autocomplétion et historique des commandes. Il peut également s’utiliser sous forme de notebook dans un navigateur. De nombreuses bibliothèques sont disponibles et peuvent être chargées dynamiquement. Ainsi, il est très aisé de préparer des présentations dynamiques avec démonstration Python en temps réel et image générée directement dans un navigateur. IPython permet aussi de déployer les notebooks sur un site web. C’est donc un outil très puissant à la fois pour expérimenter avec Python mais aussi pour préparer des présentations interactives.

Pas plus de mots, lors du meetup, nous avons pu voir des résultats assez chouettes que vous invités à expérimenter par vous-même ici : Dataviz avec iPython.

Merci à tous pour votre présence et à très bientôt :) !

[Biologeek] Cours IUT : Javascript et jQuery

Publié le 2014-11-29 11:00:00

Le jour où l’on chercha à imposer l’enseignement obligatoire au Tibet, on se heurta à la résistance des femmes.
— Mais ils sont fous ces hommes, de vouloir enlever nos enfants pour les instruire à un âge où ils ont tant de choses à apprendre. Instruire signifie imposer des idées qui ne sont pas celles des enfants. C’est une offense au droit de vivre de l’enfant. Dans une culture qui n’est pas notre culture occidentale, un enfant n’appartient pas à ses parents. La tradition veut qu’il soit donné dès sa naissance à l’Univers (qui est vie et mort) et le respect que les parents lui doivent est fait du même respect qu’ils doivent à leurs ancêtres.
— Tu peux, dit-on aux parents, donner aux enfants ton amour, mais non tes idées. Tu peux enfanter leur corps mais non leur âme. Tu peux essayer de devenir comme eux, mais tu ne peux exiger qu’ils deviennent comme toi, car la vie est projet et non retour vers le passé.

Préface de Libres enfants de Summerhill, Maud Mannoni

Plutôt satisfait du déroulé du dernier cours qui a gagné en fluidité et en échanges. J’ai pour l’instant une personne en grande difficulté mais motivée, une personne qui s’en fout, une autre qui fait ses trucs dans son coin et les 21 autres qui progressent tant bien que mal avec plus ou moins de motivation.

On passe maintenant à du dynamique avec Javascript et jQuery (imposé). J’hésite encore à tout faire en utilisant ES 6, je compte leur laisser le choix. Mes objectifs pour cette introduction :

  • comprendre la console et le scope, en expliquant "use strict" et les IEFF (function(){ /* code */ }());
  • comprendre l’écoute d’événements, avec addEventListener(’action’, fonction)
  • savoir utiliser les sélecteurs natifs et jQuery, via document.getElementsByTagName, document.getElementsByClassName, document.querySelectorAll et document.querySelector vs. $(’’)
  • savoir utiliser les manipulations du DOM, via .innerHTML et peut-être document.createDocumentFragment vs. .append(’’)
  • savoir modifier des classes CSS, via el.classList.add/remove/contains vs. $(el).addClass/removeClass/hasClass
  • savoir modifier des propriétés CSS, via el.style.property = ’foo’ vs. $(el).css({ property: ’foo’ })

Je ne compte pas aller vers des concepts de type programmation fonctionnelle avec les map, reduce, filter et compagnie faute de temps et de niveau. Je ne vais pas non plus essayer de jongler entre les animations jQuery et ce que l’on peut faire maintenant en CSS. Quelques liens pour approfondir :

Il faut aussi que je leur donne quelques tricks pour Sublime Text qui leur a été imposé par le précédent intervenant et la série des awesome pour HTML 5, CSS et Javascript. Et que je me retienne de les assommer de liens :-).

Il serait peut-être temps de leur parler de ces billets de blog comme ressources pour garder une trace et des liens en plus de leur travail en groupe. Je ne voudrais pas leur spoiler les cours non plus vu que je publie à l’avance… peut-être faire un point sur la curiosité et le googling de leurs profs ? Ou pas, si ça se trouve certains me lisent déjà.

[Biologeek] Dos et posture

Publié le 2014-11-28 11:00:00

Il existe un lien entre la typographie web et les maux de dos ; il suffit de composer votre texte en petits caractères et vous inviterez naturellement le lecteur à se pencher sur son écran pour les lire. Quoiqu’on en dise, le premier réflexe d’un lecteur ne sera pas de grossir le texte par des moyens techniques. Son premier réflexe sera d’ajuster sa posture, se rapprocher, sans même en avoir conscience.

[…]

Si vous pensez que cela est mineur, c’est que vous n’avez pas (encore ?) de véritables problèmes de dos, que vous récupérez rapidement des fatigues occasionnées par ces sollicitations répétées, ou que vous ne mesurez pas encore ce que ces micro-ajustements de posture peuvent occasionner insidieusement au terme de plusieurs heures, semaines, mois, années, de pratique (moi oui, c’est pour cela que je vous en parle).

Typographie et mal de dos

J’ai découvert récemment que j’avais tout comme Emmanuel des problèmes de dos occasionnés par la combinaison d’un déséquilibre du bassin et d’une mauvaise posture. Si le premier est quasi-inné vu qu’il proviendrait d’un siège décomplété, le second est dû aux 10 dernières années passées sur un ordinateur portable (dont les 5 dernières sur un 11 pouces…). Même en diversifiant les positions, le dos en pâtit. Si vous ajoutez à cela le port régulier d’un petit bonhomme de 10kg et l’apprentissage de nouveaux sports de manière intensive vous obtenez une colonne vertébrale qui fait pâlir mon ostéopathe.

Si vous avez mal entre les omoplates, vous souffrez peut-être du même problème. Depuis que j’y fais attention, je me rends compte qu’il y a un nombre assez important de geeks qui ont cette posture un peu voûtée. Quelques conseils pour retrouver une bonne posture :

  • adaptez votre poste de travail, et pas uniquement physiquement avec un grand écran bien positionné : augmentez la taille de police de vos applications pour avoir l’impression d’être poussé par l’écran (je vous assure que c’est perturbant au début mais ça marche, j’en suis à 18/20px) ;
  • ayez l’impression d’avoir une ventouse/un grappin/ce-qui-vous-fait-kiffer sur l’arrière du sommet du crâne qui vous tire en permanence pendant les 66 prochains jours (c’est le temps nécessaire pour prendre une habitude posturale) : au début doucement car vos muscles ne sont plus suffisamment développés pour avoir la bonne posture ;
  • si vous avez la chance d’avoir un lit électrique, adaptez-le à la position qui vous semble la moins inconfortable mais qui vous étire progressivement le dos quand même, ça serait dommage de rester voûté la nuit ;
  • travaillez la souplesse de vos épaules et ne pratiquez pas d’activités qui désalignent votre colonne (mauvaise position en natation par exemple).

Au passage si vous n’utilisez pas f.lux ou équivalent c’est bien dommage pour vos yeux. De même si vous ne pouvez pas régler la luminosité de votre écran rapidement et régulièrement.

Pour ce qui est du bassin, il s’agit avant tout de prendre de nouvelles habitudes : croisement de pieds, de jambes, positionnement sur une seule jambe à l’attente, couché sur un bras, etc doivent maintenant s’effectuer sur le côté qui vous semble le moins naturel. Bien s’étirer pour ouvrir le bassin et pratiquer le squatting est un plus même si vous n’êtes pas assez souple pour tenir tout seul.

Dernier conseil si vous devez porter une charge lourde sur le côté : gainez.

[afpyro] AFPyro à Lyon - mercredi 26 novembre

Publié le 2014-11-26 00:00:00

Un Afpyro aura lieu le mercredi 26 novembre à partir de 19h à l’Antre Autre - 11 rue Terme - 69001 Lyon.

Cet apéro python sera l’occassion de rencontrer à nouveau les gens de l’AFUP/apéro PHP, autour d’une présentation sur Ruby. Ruby est un langage open source qui met l’accent sur la simplicité et la productivité.

L’Antre Autre est un lieu où nous pouvons discuter autour d’un verre, et, pour ceux qui le souhaitent, prendre un repas.

Pour se rendre à l’Antre Autre :

  • en métro : arrêt Hôtel de Ville
  • en bus : lignes C13 et C18 arrêt Mairie du 1er ou lignes 19, C14 et C3 à l’arrêt Terreaux
  • en vélo’v : stations Place Sathonay, Carmélites Burdeau, Place de la paix

[unlish] Nose, coverage, and CubicWeb

Publié le 2014-11-25 13:11:14
CubicWeb
Writing unittests in CubicWeb cubes requires to use pytest, a test runner provided by logilab-devtools. Trying to use an other test runner is problematic, if not doomed to fail, as well as doing code coverage.
Fortunately, we can do something about it.


nose

Using nosetests to run the tests immediately fails with an obscure:
TypeError: unbound method __init__() must be called with SkipAwareTextTestRunner instance as first argument (got TextTestRunner instance instead)

After some digging, I discovered that CubicWebTC, from which we inherit all the test cases, ultimately depends on logilab pytest... which is meant to be a test runner, or so it should.
Logilab pytest, as a runner, introduce features missing from the early versions of unittests. To do so, it monkey-patch unittests itself. And I have a feeling that nose is doing something similar... which leads to the ugly error we have.
The solution is to un-monkey-patch unittests, by including these few lines somewhere loaded before any of the test (we do that in test/__init__.py):
import unittest
save_testrunner = unittest.TextTestRunner

import logilab.common.pytest # noqa
unittest.TextTestRunner = save_testrunner
After that, we can happily use nose to run the cube unittests!

coverage

The Logilab pytest tool is supposed to do code coverage measurement. Thing is: 1) I could not get it working 2) we want to use another test runner.
The naïve approach, using directly coverage or the cover extension of nose (or py.test), unfortunately fails because pytest is still messing with the trace function. The result will invariably be a coverage of 0%.
To avoid CubicWebTC to call any of the tracing-related functions of pytest, we simply inject noop() operations where they are used:
def noop(): pass

import cubicweb.devtools.testlib

cubicweb.devtools.testlib.pause_tracing = noop
cubicweb.devtools.testlib.resume_tracing = noop

And voilà!

In the end, we can use the test runner we want and get coverage to work properly. It remains a hackish workaround though, I think we ultimately need to cut the dependency from CubicWebTC to logilab.devtools.pytest.

[Biologeek] Cours IUT : Responsive et Documentation

Publié le 2014-11-23 11:00:00

Un exemple de manque de pragmatisme : j’ai déjà vu sur un projet, les intégrateurs faire toute l’intégration d’un site avec flexbox, puis passer des jours à tout refaire dans une autre feuille de style pour IE, alors qu’il était établi dès le départ que IE8 était dans la cible. Ils avaient envie d’utiliser flexbox, ce qui est compréhensible, mais dans ce contexte c’était une perte de temps pour tout le monde. La bonne technique aurait du être de faire une version correcte sur IE8, avec les techniques utilisables (ça ne manque pas), et d’ajouter ensuite les beaux dégradés, ombres, etc… que permet CSS3.

Attitude et éthique du développeur.

La dernière session des cours que je donne à l’IUT a permis d’attaquer un projet qui servira de fil rouge. La plupart se sont mis en groupe de 2 ou 3 et j’ai 2 personnes qui ont préférées faire cavalier seul, l’une pour tout comprendre et l’autre pour garder son indépendance. La rétrospective nous a permis de discuter des améliorations possibles :

  • aborder tout ce qui est relatif à l’approche mobile et responsive ;
  • avoir la possibilité d’afficher des choses sur le vidéoprojecteur (2 fails consécutifs là-dessus avec un adaptateur oublié la première fois et un vidéoprojecteur incompatible la seconde…) ;
  • faire un goûter.

Le prochain cours va donc mettre l’accent sur l’adaptation aux différentes résolutions à l’aide des media-queries en présentant les différents outils comme responsive.is ou des approches comme la responsive typography. Il existe même des moyens de visualiser les principes de base ou de réfléchir en terme de responsive philosophy. Une première étape sera de pouvoir modifier leur menu géré avec Flexbox en changeant la flex-direction de row à column par exemple. Je ne compte pas aller jusqu’à la gestion des différentes résolutions d’images, il y a déjà bien assez à faire en parlant de contenu.

J’ai préparé des cookies pour la pause du goûter, l’occasion de parler de préservation de la vie privée ? :-)

La seconde partie va encore une fois être l’occasion de les mettre en situation en faisant tourner les sources des différents projets entre les groupes et en leur demandant une amélioration mineure. L’occasion de voir à quel point il est difficile de reprendre un projet et l’intérêt d’une documentation haut niveau en plus du styleguide qu’ils ont commencé à faire lors du dernier cours.

Si j’ai un peu de temps on abordera aussi les notions de performances web car j’ai pu remarquer à quel point les élèves sont enclins à rajouter des polices ou des images assez lourdes. C’est l’intérêt d’avoir demandé à récupérer tous les projets par email en imposant d’avoir moins d’1Mo par site. J’ai ainsi pu leur faire un retour personnalisé sur les choses à améliorer, on verra ce qu’ils en ont fait.

[cubicweb] CubicWeb roadmap meeting on November 6th, 2014

Publié le 2014-11-12 09:22:00

The Logilab team holds a roadmap meeting every two months to plan its CubicWeb development effort. The previous roadmap meeting was in September 2014.

Here is the report about the November 6th, 2014 meeting. Christophe de Vienne (Unlish) joined us to express their concerns and discuss the future of CubicWeb. Dimitri Papadopoulos (CEA) could not come.

Versions

Version 3.17

This version is stable but old and maintainance will continue only as long as some customers will be willing to pay for it (current is 3.17.17).

If you're still using 3.17, you should go directly to 3.19.

Version 3.18

This version is stable but old and maintained (current is 3.18.6).

Version 3.19

This version is stable and maintained (current is 3.19.5).

Version 3.20

This version is still under development but should be released very soon now (expected next week). Its main feature being the inclusion of CWEP-002 (computed attributes and relations), along with many small improvement patches.

For details read list of tickets for CubicWeb 3.20.0.

We would have loved to integrate the pyramid cube in this release, but the debian packaging effort needed by the pyramid stack is quite big and is acceptable if we target jessie only (at decent price).

Version 3.21

For now, the roadmap for 3.21 is still the complete removal of the dbapi, the merging of Connection and ClientConnection, and possibly including CWEP-003 (adding a FROM clause to RQL).

Integrate the pyramid cube to provide the pyramid command if the pyramid framework can be imported.

Integration of CWEP-004 is being discussed.

Version 4.0

We expect to accelerate development of CubicWeb 4, which exact roadmap is still to be discussed, but we may already want:

  • be pyramid-based (remove twisted, auth management, etc.),
  • do not have anything left of old dbapi and ClientConnection,
  • integrate squareui as main (and only) web-ui "template" or remove web generation (almost) completely from cubicweb-core and provide it only through the cube system.

CWEPs

Here is the status of open CubicWeb Evolution Proposals:

to be written

Work in progress

Some work is in progress around CKAN, DCAT and othr Open Data and Semantic Web related technologies.

Agenda

Next roadmap meeting will be held at the beginning of january 2015 at Logilab, and Christophe and Dimitri (or Yann) are invited.

Open Discussions

Migration:

  • AppObjects should not be loaded by default
  • Have a look at Alembic the migration tool for SQLAlchemy and take inspiration from there

[logilab] PyconFR 2014 : jour 1, bus de communication, packaging et fin

Publié le 2014-11-04 19:26:00

Suite à :

XBUS

Florent Aide nous a présenté son projet XBUS, un bus de communication pour les applications. L'idée est de gérer l'historique : pour faire parler des applications métier entre elles, on les connecte toutes au même bus. Dans certains cas, notamment quand la sécurité des données est en jeux, l'application qui traite le message renvoie un accusé de réception et de traitement (ACK).

Côté technique, il s'agit de :

  • un cœur écrit en Go
  • zmq pour la communication
  • Python pour la logique

Lors des questions un projet similaire a été mentionné : autobahn. Le projet XBUS est libre et publié sur bitbucket.

Comment le packaging m'a simplifié la vie

Étant donné qu'à Logilab, nous avons des avis assez arrêté sur les questions de packaging, je suis allé voir cette conférence.

Xavier Ordoquy nous a présenté en détail virtualenv (pyvenv directement dans python à partir de 3.4) ainsi que l'outil pip.

Historiquement pypi a été instable, mais la situation s'est améliorée depuis qu'il est sur un CDN. Il y a un travail en cours sur la sécurité (vérification d'intégrité, ssl obligatoire etc). devpi permet d'avoir un pypi en interne comme cache, mais aussi comme système de "staging" avant de publier sur le pypi "officiel".

Selon Xavier, la guerre des distutils, python.packaging, distutils2, distribute, etc est finie. Il faut à présent utiliser setuptools et le connaître sur le bouts des doigts. Xavier nous recommande de copier un setup.py pour démarrer nos projets, par exemple celui de sentry.

Côté numéro de version, il faut aller lire la PEP440 Version Identification and Dependency Specification.

extra_requires permet de faire : pip install sentry[postgres] qui installe sentry mais aussi les dépendances pour le faire marcher avec PostgreSQL.

Côté packaging, il va falloir selon Christophe apprendre à utiliser wheel et stevedore (code).

Lors des questions, un membre du public mentionne le projet diecutter (docs, pypi).

Support de présentation : https://speakerdeck.com/xordoquy/packaging-pratique-fr

Autres liens collectés

  • Pour travailler sur les docstrings d'un projet python, pyment peut être utile.
  • fedmsg est un bus de communication utilisé chez fedora/redhat pour un grand nombre d'applications, il y a probablement de bonnes choses dedans. Il y a un début de travail sur un bus similaire chez debian

Prochain épisode

Prochain épisode: jour 2

[logilab] PyconFR 2014 : jour 1, frameworks web et gestion de source

Publié le 2014-11-04 11:28:00

Suite de pyconfr 2014 jour 1 épisode 1.

Performance des frameworks web : Python vs the world

Ronan Amicel nous a présenté le travail de benchmark publié par TechEmpower. Ces tests et résultats sont forcement faux et biaisés, mais le code source des tests est publié en libre et il est donc possible d'apporter des corrections via le projet sur github

Pour l'instant, Python3 serait plus lent que Python2, mais on peut espérer que Python3 rattrape son retard, puisqu'il est toujours développé. La comparaison avec pypy est surprenante, celui-ci est bien plus lent, l'hypothèse étant qu'il est ralenti lorsqu'il parle au driver mysql. En revanche, pour le test pypy + tornado, les performances peuvent être meilleures que nodejs car tornado est écrit en pur python il peut être optimisé par pypy.

Dans le comparatif entre python et php, un acteur surprenant est phalcon qui a pris le parti de tout coder en C (plutôt qu'une partie seulement comme on peut le trouver dans nombre de projets python).

Support de présentation : https://speakerdeck.com/ronnix/performance-des-frameworks-web-python-vs-the-world-v1-dot-1

CubicWeb - Vos données ont du sens

Nous attendions avec impatience cette présentation, et Christophe de Vienne a très bien présenté CubicWeb, le framework web dont Logilab est à l'origine.

https://www.logilab.org/file/269991/raw/logo-cubicweb.png

Après une courte introduction aux concepts du web sémantique (les URIS, les relations, le Linked Data), il a appuyé sur la nécéssité de donner du sens aux données que l'on stoque dans nos applications. Il a expliqué la finesse des réglages dans le moteur de permissions de CubicWeb.

Il a expliqué certaines fonctionnalités intéressantes selon lui dans Cubicweb :

  • les hooks: équivalent des procédures stockées déclenchées par des triggers, ils sont écrits en Python et permettent de modifier des données en cascades, implémenter des règle de gestion ou générer des notifications.
  • les adaptateurs : permettent de maximiser la réutilisation de code en adaptant une entité à une nouvelle interface

Selon Christophe, CubicWeb permet de développer une "base de donnée métier" strictement structurée, mais restant souple. Il a expliqué que l'interface par défaut n'est pas très sexy, mais qu'elle est néanmoins fonctionnelle comme backend d'édition.

Une petite introduction aux cubes qui sont les "plugins" ou les "extensions" dans le monde CubicWeb, ils contiennent :

  • un schéma
  • du code métier
  • des vues
  • des contrôleurs

Pour manipuler les données, CubicWeb utilise RQL, qui a été inventé avant SPARQL (langage de requête du web sémantique) et est plus pragmatique et lisible. Une fonctionnalité notable de RQL : plus besoin d'écrire des jointures SQL !

Finalement Christophe a conclu en présentant le mariage de Pyramid et Cubicweb. Selon lui, en regardant dedans, ils ont des philosophies communes. Le code permettant de développer une application Pyramid sur une base CubicWeb est publié sur la forge de CubicWeb. Christophe a aussi expliqué qu'il pousse des modifications pour que CubicWeb soit plus accessible aux développeurs habitués aux modes de développement "à la python".

Support de présentation : https://dl.dropboxusercontent.com/u/36590471/pyconfr-2014-pres-cubicweb/index.html

La gestion de version, ce problème tellement simple…

Pierre-Yves David (marmoute) nous a concocté un petit panorama des problèmes traités par les gestionnaires de source, avec des anecdotes de problèmes non-triviaux et quelques rappels historiques sur notre "science" informatique (merci les encodages!) Pierre-Yves s'est concentré sur les systèmes de gestion de version de "nouvelle génération", les outils décentralisés (hg, git, bzr). Forcément, étant donné qu'il travaille sur mercurial (et oui, celui écrit en python) il s'est concentré sur celui-là.

http://mercurial.selenic.com/images/mercurial-logo.png

Quand il travaillait chez Logilab, Pierre-Yves a notamment rajouté à Mercurial la notion de changeset obsolete et de phase pour faciliter la revue de code et le travail en équipe.

Manipuler son code python avec RedBaron

baron et RedBaron sont des projets assez prometteurs (et assez dingues) de manipulation de code en utilisant du code (plutôt que des éditeurs).

Laurent Peuch est revenu sur les outils historiques du domaine : rope qui a pris la suite de bicycle repair man. Il y a aussi pyfmt par le même auteur, et autopep8 écrit par d'autres.

Un exemple qui m'a parlé : ajouter @profile sur toutes les fonctions d'un script devient faisable en 3 lignes de python, et inversement pour les enlever. À suivre...

Support de présentation : https://psycojoker.github.io/pyconfr-redbaron/presentation.html

Prochain épisode

Prochain épisode: jour 1, bus de communication, packaging et fin

[Biologeek] Flux et données

Publié le 2014-11-04 11:00:00

Probablement une des choses qui change le plus quand on passe d’une architecture dite d’ « entreprise » à l’architecture d’un pure player du web, c’est l’orientation nette vers une logique de flux.

Un architecte d’entreprise vous présentera son architecture en commençant par les grands blocs applicatifs puis continuera par le système d’échange et d’intégration des données entre les différents systèmes applicatifs.

A l’inverse, l’architecte d’un pure player présentera son architecture dans la perspective d’un flux : de la collecte des données à leur mode de persistance en passant par les divers traitements. On a tout de suite le sentiment d’avoir l’orchestration temporelle d’une suite d’événements.

Dans un cas on met l’accès sur les données comme ressources applicatives, dans l’autre on met l’accent sur le flux des données. Là où la première conception est plutôt spatiale et statique, la deuxième est plutôt temporelle et dynamique.

De l’intégration des données

Je vous invite à aller lire le billet complet de Christian et le premier commentaire de Gautier. Il y est question de dualité entre des données stockées dans des bases distribuées et un système de log globalisé. Là où ça devient intéressant, c’est lorsque l’on rapproche ces réflexions de ce qu’a fait Facebook avec Flux :

Flux is the application architecture that Facebook uses for building client-side web applications. It complements React’s composable view components by utilizing a unidirectional data flow. It’s more of a pattern rather than a formal framework, and you can start using Flux immediately without a lot of new code.

Il n’y a plus d’opposition entre statique et dynamique mais une unidirectionnalité du flux de dynamisation du statique. (Ça c’est pour Damien :p.) La problématique ne se pose plus en termes de stockage et de transfert mais en terme d’évolutivité des données. Ainsi on s’abstrait de la nécessité d’un log global en ayant des flux indépendants et isolés, le stockage peut être distribué c’est le dispatcher qui va s’assurer de la cohérence de la modification des données. On se retrouve avec une approche hybride qui est à la fois spatiale et temporelle. L’intégration et le croisement des données est — si l’on fait abstraction des problèmes de performances — plus politique que technique (cf. OpenData et citoyenneté ou OpenData et évaluation), il ne faut pas concentrer les données dans un même log mais réunir les acteurs dans une même pièce ;-).

Je suis extrêmement surpris que les vieux concepts réutilisés dans Flux n’aient pas donné lieux à une prolifération de nouveaux frameworks web. Je suis presque sûr que l’on peut combiner cette approche à asyncio

[logilab] PyconFR 2014 : jour 1, BDD, postgresql et asyncio

Publié le 2014-11-03 19:19:00

J'ai eu le plaisir de participer à la conférence PyconFR 2014, voici quelques notes sur les présentations auxquelles j'ai pu assister. Étant donné la longueur, je vais publier sous forme de plusieurs billets de blog.

http://www.pycon.fr/2014_static/pyconfr/images/banner.png

BDD avec Behave

Le Behaviour Driven Develpment en Python peut se faire avec behave. Dans un premier temps on décrit en language "naturel" le test. Dans un deuxième temps on implémente les tests unitaires pour faire le lien avec la description behave, et on met les chaines de caractères dans un decorateur @given, puis @when puis @then.

Les scenarios behave sont utiles pour le dévelopement, pour la documentation, pour la formation des nouveaux arrivants et même pour faciliter la supervision des applications en production.

Les diapos de la présentation sont disponible sur slideshare.

Python + PostgreSQL

Stéphane Wirtle nous a présenté comment les relations étroites entre le monde de Python et celui de PostgreSQL.

https://avatars1.githubusercontent.com/u/2947270?v=2&s=400

Points à noter :

  • FDW : Foreign Data Wrapper, dont voici une liste sur le wiki de PostgreSQL
  • PL (Procedure Language) : PL/C, PL/Python, PL/v8, etc. pour étendre sa base de donnée. Les procedure language SQL sont par défault "trusted", les autres ne sont pas trusted par défaut. Dans CubicWeb, nous utilisons PL/Python pour la recherche plein texte et la lemmatisation du texte.

Pour ceux qui souhaiteraient essayer un ORM, Stéphane Wirtle conseille Peewee ORM.

Pour les migrations de schema SQLalchemy, Stéphane Wirtle nous conseille Alembic.

Parfois un ORM peut générer beaucoup de requêtes SQL et il y a de la place pour une optimisation en tapant directement du SQL. Pour évaluer la surcharge dûe à l'ORM, on peut utiliser pgBadger.

Support de présentation : https://speakerdeck.com/matrixise/python-and-postgresql-a-wonderful-wedding/

Un serveur fiable avec python 3.4

Après une petite introduction aux principes de concurrence, Martin Richard nous a présenté un retour d'expérience sur l'utilisation du module asyncio introduit dans python 3.4. Il permet de ne plus avoir à utiliser twisted ou gevent.

Les ressources et bibliothèques qui utilisent asyncio sont recensées sur http://asyncio.org/

objgraph permet de d'analyser des structures de données Python pour identifier des fuites memoire.

memoryview introduit dans python3.4 permet de faire "référence" à une structure de données sans la copier, ce qui peut être très pratique mais rend complexe la gestion de code.

Martin a utilisé @lru_cache pour mettre en cache les resultats d'un calcul en utilisant la politique de cache "Least Recently Used (LRU)".

Support de présentation : http://marti.us/t/pyconfr-2014/

[unlish] pip install -e / setup.py develop on a cube

Publié le 2014-11-02 19:44:48

The current layout of CubicWeb cubes is not setuptools friendly, and does not permit to use the "develop" mode. The CWEP 004, currently under discussion, aims to solve that problem, and once adopted make life easier for the developers.

Meanwhile, some people (like us at Unlish) would like to use the develop mode anyway, so that we can work on a cube without cloning the whole tree of CubicWeb requirements.

After a few experiments, it turns out we can tweak the virtualenv after pip install -e is run on the cube, and have the benefit of it.

The solution I describe below allows to work on both the cube and the unittests, importing from "cubes.thecube" and "cubes.anothercube" in a virtualenv. It can be applied to several cubes in the same virtualenv. It does *not* apply to the other cubicweb packages.

From this point, 'thecube' is the cube that we work on, 'anothercube' is any other cube involved in the application we develop.

Problem 1 - the cubes path

Once pip install -e has been run the cube on which it was launched is not usable because it is not present in the cube path.

We do not want to add the parent directory of our cube to CW_CUBES_PATH because:
  • When importing from cubes.acube, and because "cubes" is not a proper namespace, we have issues
  • The spirit of virtualenv is that where the project was checked out does not matter -> we do not want to put restriction on where it can be put in the filesystem.

Solution

From within the virtualenv :

ln -s $(pwd) $VIRTUAL_ENV/share/cubicweb/cubes/thecube

Problem 2 - the python path

  1. pip install -e add our directory to the interpreter path. It is a problem because it pollutes the root namespace, it not masks some modules when the names match (for example in unlish we have a 'markdown.py' file).
  2. for some reason I did not identified, I could not import from cubes.xxx because the virtualenv cubes path is not added to the syspath like I expected it to (I may have done something wrong on this matter).

Solution

  1. Remove our directory from the virtualenv path
    PTH=$VIRTUAL_ENV/lib/python2.7/site-packages/easy-install.pth
    grep -v $(pwd) $PTH > .pth.tmp
    mv .pth.tmp $PTH
  2. Add the virtualenv cubes path to the python path
    export PYTHONPATH=$VIRTUAL_ENV/share/cubicweb
    This last command has to be done each time the virtualenv is activated, it is recommended to add it to the 'activate' script, OR postactivate script if you are using virtualenvwrapper (which I recommend too). 

    Put it all together

    The following script does all that for you, and has to be run after each run of pip install -e.
    Note that it will overwrite your postactivate script, set CW_MODE=user and define a 'ctl' alias, so you may need to modify it before using it.

    #!/bin/bash

    MYPATH=$(pwd)
    MODNAME=$(python -c "import __pkginfo__; print __pkginfo__.modname")

    if [ -z "$VIRTUAL_ENV" ]; then
    exit 1
    fi

    if [ -n "$VIRTUAL_ENV/bin/postactivate" ]; then
    cat >>$VIRTUAL_ENV/bin/activate <<EOF
    . $VIRTUAL_ENV/bin/postactivate
    EOF
    fi

    cat >$VIRTUAL_ENV/bin/postactivate <<EOF
    export CW_MODE=user
    export PYTHONPATH=$VIRTUAL_ENV/share/cubicweb

    alias ctl=cubicweb-ctl
    EOF

    rm -rf $VIRTUAL_ENV/share/cubicweb/cubes/$MODNAME
    ln -s $MYPATH $VIRTUAL_ENV/share/cubicweb/cubes/$MODNAME

    PTH=$VIRTUAL_ENV/lib/python2.7/site-packages/easy-install.pth
    grep -v $MYPATH $PTH > .pth.tmp
    mv .pth.tmp $PTH

    echo "Tweaked virtualenv $VIRTUAL_ENV"
    echo "Don't forget to re-activate it:"
    echo ""
    echo " workon $(basename $VIRTUAL_ENV)"

    To conclude, this is only a hackish workaround to wait for the real solution: reforming the cubes in cubicweb.

    (this post was initially a mail on the cubicweb mailing-list)

[j-mad] Django 1.7 et écriture de tests, petites explorations

Publié le 2014-11-02 16:41:50
Je me suis enfin lancé dans l’écriture d’une app django gérant les badges (ou les succès si vous préférez). L’objectif étant de pouvoir réécrire de zéro histoires de rôlistes. L’idée était de tenter de faire une vraie app django, en mode réutilisable, histoire que peut-être des gens puissent trouver intéressant de l’utiliser. Je me suis [...]

[unlish] Unlish à PyconFR

Publié le 2014-10-29 22:40:55
Pour la deuxième année consécutive, Unlish était sponsor de Pyconfr, organisé par l'AFPy, qui réuni chaque année plus de 200 développeurs venus de toute la France et d'ailleurs.

Ces deux jours passés dans les amphis de l'université de Lyon ont été l'occasion de retrouver de nombreuses têtes connues, découvrir des usages de python, et faire connaître CubicWeb, un élément essentiel de notre architecture technique.

Nous y avons parlé robotique, tests unitaires, programmation asynchrone, Web des données, refactoring, gestion de version, pyramid et même, des choses qu'on n'aime pas dans Python !


C'est la tête pleine de bons souvenirs que nous avons quittés Lyon, et nous attendons avec impatience la prochaine édition. Pour que le temps semble moins long, nous ferons peut-être un tour au FOSDEM pour Python-FOSDEM.

Merci aux organisateurs, aux orateurs, et à tous les pythoneux qui ont fait le déplacement !

[AFPy-Nantes] Meetup / Conférences Python le 18 novembre

Publié le 2014-10-27 23:00:00

Pour éviter de faire de l'ombre à la PyConFr (</joke>), nous avons décalé la prochaine rencontre des pythonistes nantais au mois de novembre.

Le meetup est donc prévu le 18 novembre, toujours à La Cantine de Nantes, à partir de 19h.

Au programme cette fois-ci, deux conférences:

  • IPython & dataviz : Quand on pense cartographie, certains pensent logiciels bureautiques, d'autres en ligne, ici nous montrerons qu'il existe d'autres voies en particulier pour l'analyse de données. Ainsi, nous vous proposons de voir l'utilisation de IPython pour découvrir des données et les cartographier. Nous pourrons ainsi introduire quelques bibliothèques pour l'analyse statistique, la manipulation de données et les représentations cartographiques.
  • Pelican : À contre-courant des frameworks web « full-stack », complexes et lourds, se trouve Pelican, et les générateurs de sites statiques. Pourquoi opter pour une approche si minimaliste ? Que peut-on en tirer ? Découvrez l’utilisation de Pelican, ses forces, ses limites, et comment les contourner.

Comme d'habitude, nous espérons vous compter parmi nous pour ces conférences, ainsi pour le verre qui s'en suivra probablement :).

Pour vous tenir informé du contenu exact de l'évènement, ou pour faire part de vos suggestions, n'hésitez pas à vous inscrire à la liste de diffusion des pythonistes nantais.

Vous pouvez aussi nous rejoindre sur le chan IRC de l'AFPy Nantes. :)

[afpyro] AFPyro à Lyon - samedi 25 octobre

Publié le 2014-10-25 00:00:00

Un Afpyro aura lieu le 25 octobre à partir de 18h30 au 1929 Label Époque, situé `10 rue de la république, Lyon <http://www.openstreetmap.org/node/1865407690#map=18/45.76571/4.83582`_.

Cet apéro Python accueillera les participants à PyConFr.

Toutes les infos sur la soirée sur le site de PyConFr.

[tarek] Web Application Firewall

Publié le 2014-10-24 14:41:00

Web Application Firewall (WAF) applied to HTTP web services is an interesting concept.

It basically consists of extracting from a web app a set of rules that describes how the endpoints should be used. Then a Firewall proxy can enforce those rules on incoming requests.

Le't say you have a search api where you want to validate that:

  • there's a optional before field that has to be a datetime
  • you want to limit the number of calls per user per minute to 10
  • you want to reject with a 405 any call that uses another HTTP method than GET

Such a rule could look like this:

"/search": {
    "GET": {
        "parameters": {
            "before": {
                "validation":"datetime",
                "required": false
            }
        },
        "limits": {
            "rates": [
                {
                    "seconds": 60,
                    "hits": 10,
                    "match": "header:Authorization AND header:User-Agent or remote_addr"
                }
            ]
        }
    }
}

Where the rate limiter will use the Authorization and the User-Agent header to uniquely identify a user, or the remote IP address if those fields are not present.

Note

We've played a little bit around request validation with Cornice, where you can programmatically describe schemas to validate incoming requests, and the ultimate goal is to make Cornice generate those rules in a spec file independantly from the code.

I've started a new project around this with two colleagues at Mozilla (Julien & Benson), called Videur. We're defining a very basic JSON spec to describe rules on incoming requests:

https://github.com/mozilla/videur/blob/master/spec/VAS.rst

What makes it a very exciting project is that our reference implementation for the proxy is based on NGinx and Lua.

I've written a couple of Lua scripts that get loaded in Nginx, and our Nginx configuration roughly looks like this for any project that has this API spec file:

http {
    server {
        listen 80;
        set $spec_url "http://127.0.0.1:8282/api-specs";
        access_by_lua_file "videur.lua";
    }
}

Instead of manually defining all the proxy rules to point to our app, we're simply pointing the spec file that contains the description of the endpoints and use the lua script to dynamically build all the proxying.

Videur will then make sure incoming requests comply with the rules before passing them to the backend server.

One extra benefit is that Videur will reject any request that's not described in the spec file. This implicit white listing is in itself a good way to avoid improper calls on our stacks.

Last but not least, Lua in Nginx is freaking robust and fast. I am still amazed by the power of this combo. Kudos to Yichun Zhang for the amazing work he's done there.

Videur is being deployed on one project at Mozilla to see how it goes, and if that works well, we'll move forward to more projects and add more features.

And thanks to NginxTest our Lua script are fully tested.

[logilab] PyconFR 2014 - on y va !

Publié le 2014-10-24 13:01:00

Pycon.fr est l’événement annuel qui rassemble les utilisateurs et développeurs Python en France, c'est une conférence organisée par l'AFPY (L'Association Francophone Python). Elle se déroulera cette année sur 4 jours à Lyon : 2 jours de conférences, 2 jours de sprints.

http://www.pycon.fr/2014_static/pyconfr/images/banner.png

Nous serons présents à PyconFR les samedi et dimanche pour y voir les présentation nombreuses et prometteuses. Nous assisterons en particulier à deux présentations qui sont liés à l'activité de Logilab :

On espère vous y croiser. Si tout va bien, nous prendrons le temps de faire un compte rendu de ce qui a retenu notre attention lors de la conférence.

[afpyro] AFPyro à Lyon - vendredi 24 octobre

Publié le 2014-10-24 00:00:00

Un Afpyro aura lieu le vendredi 24 octobre à partir de 19h à l’Antre Autre - 11 rue Terme - 69001 Lyon.

Si jamais vous venez à PyConFr 2014, et que vous arrivez le vendredi soir, venez retrouver d’autres participants à l’endroits qui accueille la plupart des afpyros lyonnais !

L’Antre Autre est un lieu où nous pouvons discuter autour d’un verre, et, pour ceux qui le souhaitent, prendre un repas.

Pour se rendre à l’Antre Autre :

  • en métro : arrêt Hôtel de Ville
  • en bus : lignes C13 et C18 arrêt Mairie du 1er ou lignes 19, C14 et C3 à l’arrêt Terreaux
  • en vélo’v : stations Place Sathonay, Carmélites Burdeau, Place de la paix

[AFPy Salt-fr] Annonce : Logilab présente Saltstack le 3 novembre à la cantine Toulouse

Publié le 2014-10-23 22:00:00

Logilab vous invite le lundi 3 novembre à une présentation de Salt à la cantine de Toulouse. Cela se passera de 18 à 20h, avec une présentation suivie d'un moment convivial autour d'un apéritif afin de continuer la discussion.

Plus d'information et inscription sur la page de l'événement à la cantine.

[Biologeek] Enseignement et acquisition

Publié le 2014-10-22 11:00:00

Easier to ask for forgiveness than permission. This common Python coding style assumes the existence of valid keys or attributes and catches exceptions if the assumption proves false. This clean and fast style is characterized by the presence of many try and except statements. The technique contrasts with the LBYL style common to many other languages such as C.

EAFP

J’ai appris qu’il y avait eu une suite à l’intervention de SudWeb au sujet de l’enseignement de l’intégration lors de ParisWeb (merci Boris !). On peut dire que ça tombe au bon moment. Tout cela m’amène à faire un parallèle entre des paradigmes de langages de programmation (EAFP vs. LBYL) et l’opposition pratique vs. théorique que l’on rencontre forcément lorsque l’on souhaite transmettre ses connaissances. À quel point faut-il prévenir plutôt que guérir ? Qu’est-ce qui est le plus formateur ?

J’ai pour l’instant pris l’option très expérimentale : produisez, je vous corrige. Et j’espère bien arriver jusqu’à un point où cela deviendra : produisez, corrigez-vous ! Ce vous correspondant au groupe et aux connaissances accessibles en ligne. Mais je suis tiraillé. Ces étudiants ont la chance d’avoir une formation et je leur propose de devenir autodidactes. Est-ce que je ne les prive pas ainsi d’une théorie qui m’a manquée pour pouvoir progresser plus rapidement il y a 10 ans ? Est-ce que les trentenaires du Web (huhuhu) ne se cachent pas derrière cette mise en pratique car ils n’ont connu que ça ?

Et puis je me raccroche à la permissivité du Web, à cette inconsistence inscrite dans son ADN, à ces paquets qui errent entre 2 continents avec l’espoir d’arriver quelque part. J’imagine ces étudiants qui souhaitent à tout prix être autonomes alors qu’il va leur falloir apprendre à faire ensemble. Qui veulent appliquer de la bonne pratique sans forcément en comprendre le sens et le besoin. Je les observe, perdus mais volontaires, et je garde espoir. Ils ont encore le temps pour faire des erreurs et l’énergie pour se relever.

[afpyro] AFPyro à Lyon - mercredi 22 octobre

Publié le 2014-10-22 00:00:00

Un Afpyro aura lieu le mercredi 22 octobre à partir de 19h à l’Antre Autre - 11 rue Terme - 69001 Lyon.

Il n’y aura pas de présentation ce mois ci, mais on va s’organiser un peu pour que tout se passe bien pendant la PyConFr. Donc si jamais vous êtes lyonnais et volontaire, venez y faire un tour !

Si vous n’avez pas la possibilité de venir à l’apéro, mais que vous voulez donner un coup de main pendant PyConFr, faites signe !

L’Antre Autre est un lieu où nous pouvons discuter autour d’un verre, et, pour ceux qui le souhaitent, prendre un repas.

Pour se rendre à l’Antre Autre :

  • en métro : arrêt Hôtel de Ville
  • en bus : lignes C13 et C18 arrêt Mairie du 1er ou lignes 19, C14 et C3 à l’arrêt Terreaux
  • en vélo’v : stations Place Sathonay, Carmélites Burdeau, Place de la paix

[AFPy Salt-fr] Annonce : Meetup Salt Paris - Novembre 2014

Publié le 2014-10-20 22:00:00

Oyez, oyez salters, notre prochain meetup se déroulera le mardi 18 novembre à partir de 19h chez tinyclues qui est fier de nous héberger et de pouvoir sponsoriser cet évènement.

Voici la liste des présentations qui seront données :

  • Salt et la gestion d'un parc de postes utilisateurs, homebrew cask pour Mac et chocolatey pour Windows (Aurélien Minet - ENS Cachan)
  • Runners et modules pour générer des statistiques d´écart de l'infrastructure par rapport à sa définition (Arthur Lutz - Logilab)
  • SaltPad, l'interface que votre infrastructure mérite (Boris Feld - tinyclues)

Malheureusement, le nombre de place est limité à 30 personnes, donc dépêchez-vous de vous inscrire ici : http://framadate.org/n8u9e8ib1ffggdmt.

Vous pouvez aussi vous inscrire sur le meetup pour suivre les actualités du groupe : http://www.meetup.com/Paris-Salt-Meetup/.

tinyclues nous offrira de quoi nous désaltérer et Logilab nous fournira de quoi remplir nos estomacs, d'ailleurs si vous voulez autre chose que des pizzas, merci de répondre au sondage sur la mailing-list.

Les locaux de tinyclues c'est au

15, rue du Caire
75002 Paris
France

Métro Réaumur - Sébastopol ou Strasbourg Saint-Denis.

En espérant vous voir nombreux, saltez bien !

[AFPy-Nantes] Barcamp & micro-python

Publié le 2014-10-18 22:00:00

Pour le barcamp Python du 30 Septembre, nous étions 6 à s'être intéressés à cette mystérieuse carte micro-python. C'est donc convivialement installés autour d'une table qu'on a pu en savoir plus.

Compte rendu.

Présentation

Né d'un projet Kick-Starter, micro-python est un microcontrôleur embarquant un interpréteur d'un dialect de Python 3. Après la réussite du financement sur Kick-Starter, un exemplaire a été envoyé à tous les gens y ayant participé. Puis chaque personne s'étant manifestée sur leur newsletter a pu en avoir un. Désormais la boutique Internet est ouverte à tous. Si ça vous fait déjà rêver, c'est par ici.

C'est donc un petit joujou d'open hardware que nous avons pu voir en action. La bestiole est équipée d'un processeur ARM et coûte environ 35€. Pour l'instant on commande depuis le Royaume-Uni, donc c'est en Livres... Concernant le stockage, deux options. Une mémoire flash de 128Ko et un port pour micro-SD. Pour le reste, notre micro-copain intègre des accéléromètres. Il y a une démo sur le site pour le transformer en souris. Par contre, pas de gyroscope, donc exit la position en temps réelle native. En revanche, il existe de nombreux shield (modules additionnels) que l'on peut déjà commander et dont le prix est assez bas. On citera un afficheur LCD, un touch-pad et de quoi supporter le wi-fi. Enfin, la carte présente quatre (4) LEDs. Rouge, jaune, verte et bleue. L'intensité de cette dernière peut être réglée. La question s'est évidemment posée de l'avantage par rapport à son concurrent direct, le Raspberry Pie. Deux arguments principaux sont ressortis. D'abord la consommation électrique bien inférieure de micro-python : l'absence de processeur graphique est l'une des raisons. Il a également été évoqué les fuites de courant des ports USB du Rasberry Pie. De plus, ces derniers ne peuvent pas être désactivés, donc pas d'optimisation de la consommation possible. Second argument en faveur de micro-python, éviter l'over-kill. En effet, pour la pluspart des utilisations d'un microcontrôleur, un Raspberry Pie fait un peu office de bombe nucléaire. Petit plus de la carte, elle présente une documentation électrique fournie et claire, écrite en blanc au dos de celle-ci.

Concernant le logiciel, c'est donc un dialecte de Python 3. Cette variante est disponible et compilable sur de nombreuses architectures autres que ARM. Le code source est disponible sur GitHub. En plus de cela, il existe un repo de différentes bibliothèques adaptées pour micro-python. On peut notamment y trouver pip.

Let's roll

C'est bien mignon tout ça, mais qu'en fait-on ? me direz-vous. Pas d'impatience, voici le moment venu du test !

Que la lumière soit

On commence par sortir en boîte :). Notre démonstrateur nous sort sa plus jolie boucle while pour éclairer les LEDs en séquences. Vidéo du résultat ci-dessous avec en prime le code source en arrière plan.

Ce test est l'occasion de découvrir comment on code et déploie. Le processeur cherche successivement sur la micro-SD ou sur la flash un fichier main.py qui sert de point d'entrée au programme. Lors de l'écriture sur la mémoire flash, la LED rouge s'allume et s'éteint à la fin de l'opération. Un petit reboot et le tour est joué. Il est possible de faire de l'inlining assembleur pour optimiser les chemins critiques et un portage de l'API C de Python est disponible. De quoi s'occuper donc.

Moteur, ça tourne

Seconde démo, utilisation d'un servomoteur. Même logique concernant le code et le déploiement. Concrètement, une classe Servo permet de contrôler le servo :

brain = pyb.Servo(1)

On peut ensuite changer l'angle, en degré :

brain.angle(45)
brain.angle(-60)

Consulter l'angle courant :

servo1.angle()
-60

Et aussi changer l'angle en spécifiant un temps de transition, en millisecondes :

servo1.angle(50, 1000)

Dans le contexte de ce test, comment ne pas parler des drones ? Du coup, nous avons évoqué une conférence TED sur les drones agiles et aussi le projet open-source de drone Paparazzi.

Digression

Beaucoup d'effervescence lors de cette rencontre, et donc quelques digressions. Le sujet le plus complet était sans doute l'opposition entre pip et gestionnaire de paquets (celui du système lorsque présent) pour la gestion des bibliothèques.

pip permet d'installer des paquets Python sans gestion complexe de dépendance non python (compilateur C/C++). Couplé avec les environnements virtuels, il résout de nombreux problèmes mais reste avant tout une solution de contournement. Cependant, faire sans peut s'avérer difficile.

L'alternative beaucoup plus stable reste donc l'utilisation du gestionnaire de paquet du système. Hors toutes les bibliothèques Python ne sont pas packagées... Donc, si l'on souhaite rester rigoureux il faudra sans-doute repackager quelques bibliothèques. Il semble que ce soit la stratégie de Reddit.

Les autres projets évoqués :

[logilab] Using Saltstack to limit impact of Poodle SSLv3 vulnerability

Publié le 2014-10-15 13:01:00

Here at Logilab, we're big fans of SaltStack automation. As seen with Heartbleed, controlling your infrastructure and being able to fix your servers in a matter of a few commands as documented in this blog post. Same applies to Shellshock more recently with this blog post.

Yesterday we got the news that a big vulnerability on SSL was going to be released. Code name : Poodle. This morning we got the details and started working on a fix through salt.

So far, we've handled configuration changes and services restart for apache, nginx, postfix and user configuration for iceweasel (debian's firefox) and chromium (adapting to firefox and chrome should be a breeze). Some credit goes to mtpettyp for his answer on askubuntu.

http://www.logilab.org/file/267853/raw/saltstack_poodlebleed.jpg
{% if salt['pkg.version']('apache2') %}
poodle apache server restart:
    service.running:
        - name: apache2
  {% for foundfile in salt['cmd.run']('rgrep -m 1 SSLProtocol /etc/apache*').split('\n') %}
    {% if 'No such file' not in foundfile and 'bak' not in foundfile and foundfile.strip() != ''%}
poodle {{ foundfile.split(':')[0] }}:
    file.replace:
        - name : {{ foundfile.split(':')[0] }}
        - pattern: "SSLProtocol all -SSLv2[ ]*$"
        - repl: "SSLProtocol all -SSLv2 -SSLv3"
        - backup: False
        - show_changes: True
        - watch_in:
            service: apache2
    {% endif %}
  {% endfor %}
{% endif %}

{% if salt['pkg.version']('nginx') %}
poodle nginx server restart:
    service.running:
        - name: nginx
  {% for foundfile in salt['cmd.run']('rgrep -m 1 ssl_protocols /etc/nginx/*').split('\n') %}
    {% if 'No such file' not in foundfile and 'bak' not in foundfile and foundfile.strip() != ''%}
poodle {{ foundfile.split(':')[0] }}:
    file.replace:
        - name : {{ foundfile.split(':')[0] }}
        - pattern: "ssl_protocols .*$"
        - repl: "ssl_protocols TLSv1 TLSv1.1 TLSv1.2;"
        - show_changes: True
        - watch_in:
            service: nginx
    {% endif %}
  {% endfor %}
{% endif %}

{% if salt['pkg.version']('postfix') %}
poodle postfix server restart:
    service.running:
        - name: postfix
poodle /etc/postfix/main.cf:
{% if 'main.cf' in salt['cmd.run']('grep smtpd_tls_mandatory_protocols /etc/postfix/main.cf') %}
    file.replace:
        - pattern: "smtpd_tls_mandatory_protocols=.*"
        - repl: "smtpd_tls_mandatory_protocols=!SSLv2,!SSLv3"
{% else %}
    file.append:
        - text: |
            # poodle fix
            smtpd_tls_mandatory_protocols=!SSLv2,!SSLv3
{% endif %}
        - name: /etc/postfix/main.cf
        - watch_in:
            service: postfix
{% endif %}

{% if salt['pkg.version']('chromium') %}
/usr/share/applications/chromium.desktop:
    file.replace:
        - pattern: Exec=/usr/bin/chromium %U
        - repl: Exec=/usr/bin/chromium --ssl-version-min=tls1 %U
{% endif %}

{% if salt['pkg.version']('iceweasel') %}
/etc/iceweasel/pref/poodle.js:
    file.managed:
        - text : pref("security.tls.version.min", "1")
{% endif %}

The code is also published as a gist on github. Feel free to comment and fork the gist. There is room for improvement, and don't forget that by disabling SSLv3 you might prevent some users with "legacy" browsers from accessing your services.

[cubicweb] Exploring the datafeed API in CubicWeb

Publié le 2014-10-14 14:50:00

The datafeed API is one of the nice features of the CubicWeb framework. It makes it possible to easily build such things as a news aggregator (or even a semantic news feed reader), a LDAP importer or an application importing data from another web platform. The underlying API is quite flexible and powerful. Yet, the documentation being quite thin, it may be hard to find one's way through. In this article, we'll describe the basics of the datafeed API and provide guiding examples.

The datafeed API is essentially built around two things: a CWSource entity and a parser, which is a kind of AppObject.

The CWSource entity defines a list of URL from which to fetch data to be imported in the current CubicWeb instance, it is linked to a parser through its __regid__. So something like the following should be enough to create a usable datafeed source [1].

create_entity('CWSource', name=u'some name', type=u'datafeed', parser=u'myparser')

The parser is usually a subclass of DataFeedParser (from cubicweb.server.sources.datafeed). It should at least implement the two methods process and before_entity_copy. To make it easier, there are specialized parsers such as DataFeedXMLParser that already define process so that subclasses only have to implement the process_item method.

Overview of the datafeed API

Before going into further details about the actual implementation of a DataFeedParser, it's worth having in mind a few details about the datafeed parsing and import process. This involves various players from the CubicWeb server, namely: a DataFeedSource (from cubicweb.server.sources.datafeed), the Repository and the DataFeedParser.

  • Everything starts from the Repository which loops over its sources and pulls data from each of these (this is done using a looping task which is setup upon repository startup). In the case of datafeed sources, Repository sources are instances of the aforementioned DataFeedSource class [2].
  • The DataFeedSource selects the appropriate parser from the registry and loops on each uri defined in the respective CWSource entity by calling the parser's process method with that uri as argument (methods pull_data and process_urls of DataFeedSource).
  • If the result of the parsing step is successful, the DataFeedSource will call the parser's handle_deletion method, with the URI of the previously imported entities.
  • Then, the import log is formatted and the transaction committed. The DataFeedSource and DataFeedParser are connected to an import_log which feeds the CubicWeb instance with a CWDataImport per data pull. This usually contains the number of created and updated entities along with any error/warning message logged by the parser. All this is visible in a table from the CWSource primary view.

So now, you might wonder what actually happens during the parser's process method call. This method takes an URL from which to fetch data and processes further each piece of data (using a process_item method for instance). For each data-item:

  1. the repository is queried to retrieve or create an entity in the system source: this is done using the extid2entity method;
  2. this extid2entity method essentially needs two pieces of information:
    • a so-called extid, which uniquely identifies an item in the distant source
    • any other information needed to create or update the corresponding entity in the system source (this will be later refered to as the sourceparams)
  3. then, given the (new or existing) entity returned by extid2entity, the parser can perform further postprocessing (for instance, updating any relation on this entity).

In step 1 above, the parser method extid2entity in turns calls the repository method extid2eid given the current source and the extid value. If an entry in the entities table matches with the specified extid, the corresponding eid (identifier in the system source) is returned. Otherwise, a new eid is created. It's worth noting that the created entity (in case the entity is to be created) is not complete with respect to the data model at this point. In order the entity to be completed, the source method before_entity_insertion is called. This is where the aforementioned sourceparams are used. More specifically, on the parser side the before_entity_copy method is called: it usually just updates (using entity.cw_set() for instance) the fetched entity with any relevant information.

Case study: a news feeds parser

Now we'll go through a concrete example to illustrate all those fairly abstract concepts and implement a datafeed parser which can be used to import news feeds. Our parser will create entities of type FeedArticle, which minimal data model would be:

class FeedArticle(EntityType):
    title = String(fulltextindexed=True)
    uri = String(unique=True)
    author = String(fulltextindexed=True)
    content = RichString(fulltextindexed=True, default_format='text/html')

Here we'll reuse the DataFeedXMLParser, not because we have XML data to parse, but because its interface fits well with our purpose, namely: it ships an item-based processing (a process_item method) and it relies on a parse method to fetch raw data. The underlying parsing of the news feed resources will be handled by feedparser.

class FeedParser(DataFeedXMLParser):
    __regid__ = 'newsaggregator.feed-parser'

The parse method is called by process, it should return a list tuples with items information.

def parse(self, url):
    """Delegate to feedparser to retrieve feed items"""
    data = feedparser.parse(url)
    return zip(data.entries)

Then the process_item method takes an individual item (i.e. an entry of the result obtained from feedparser in our case). It essentially defines an extid, here the uri of the feed entry (good candidate for unicity) and calls extid2entity with that extid, the entity type to be created / retrieved and any additional data useful for entity completion passed as keyword arguments. (The process_feed method call just transforms the results obtained from feedparser into a dict suitable for entity creation following the data model described above.)

def process_item(self, entry):
    data = self.process_feed(entry)
    extid = data['uri']
    entity = self.extid2entity(extid, 'FeedArticle', feeddata=data)

The before_entity_copy method is called before the entity is actually created (or updated) in order to give the parser a chance to complete it with any other attribute that could be set from source data (namely feedparser data in our case).

def before_entity_copy(self, entity, sourceparams):
    feeddata = sourceparams['feeddata']
    entity.cw_edited.update(feeddata)

And this is all what's essentially needed for a simple parser. Further details could be found in the news aggregator cube. More sophisticated parsers may use other concepts not described here, such as source mappings.

Testing datafeed parsers

Testing a datafeed parser often involves pulling data from the corresponding datafeed source. Here is a minimal test snippet that illustrates how to retrieve the datafeed source from a CWSource entity and to pull data from it.

with self.admin_access.repo_cnx() as cnx:
    # Assuming one knows the URI of a CWSource.
    rset = cnx.execute('CWSource X WHERE X uri %s' % uri)
    # Retrieve the datafeed source instance.
    dfsource = self.repo.sources_by_eid[rset[0][0]]
    # Make sure it's parser matches the expected.
    self.assertEqual(dfsource.parser_id, '<my-parser-id>')
    # Pull data using an internal connection.
    with self.repo.internal_cnx() as icnx:
        stats = dfsource.pull_data(icnx, force=True, raise_on_error=True)
        icnx.commit()

The resulting stats is a dictionnary containing eids of created and updated entities during the pull. In addition all entities created should have the cw_source relation set to the corresponding CWSource entity.

Notes

[1]

It is possible to add some configuration to the CWSource entity in the form a string of configuration items (one per line). Noteworthy items are:

  • the synchronization-interval;
  • use-cwuri-as-url=no, which avoids using external URL inside the CubicWeb instance (leading to any link on an imported entity to point to the external source URI);
  • delete-entities=[yes,no] which controls if entities not found anymore in the distant source should be deleted from the CubicWeb instance.
[2]The mapping between CWSource entities' type (e.g. "datafeed") and DataFeedSource object is quite unusual as it does not rely on the vreg but uses a specific sources registry (defined in cubicweb.server.SOURCE_TYPES).

[logilab] Petit compte rendu du meetup postgresql d'octobre 2014

Publié le 2014-10-09 17:10:00

Hier soir, je suis allé au Meetup PostgreSQL intitulé "DBA et Développeurs enfin réunis". Après quelques bières et pizza (c'est la tradition de le faire dans ce sens), nous avons écouté 4 présentations autour de PostgreSQL après une courte introduction de Dimitri Fontaine et des sponsors (Mozilla et Novapost).

http://www.logilab.org/file/266939/raw/BzcR8UOIQAAdFMh.jpg

Jean-Gérard Pailloncy nous a parlé d'aggrégation temporelle sous contrainte d'IOPS (page wikipedia pour IOPS, au cas où). Malgré le temps court de présentation, c'était une synthèse très bien déroulée d'un projet avec des flux de données ambitieux pour des plateformes "entrée de gamme". Quelques "petites" astuces que chacun pourrait appliquer à ses projets.

Flavio Henrique Araque Gurgel nous a parlé du partitionnement de tables et des mythes qui entourent ce sujet. Dans quels cas dois-je partionner ? Beaucoup de cas de figure sont possibles, les métriques qui permettent de prendre ce genre de décisions sont nombreuses et nécessitent une bonne compréhension du fonctionnement interne des bases de données Postgresql. Il s'agissait principalement d'amener les praticiens de postgresql à se poser les bonnes questions lors de la conception de leur base de données.

Thomas Reiss et Julien Rouhaud nous ont présenté POWA (PostgreSQL Workload Analyzer). Il s'agit d'une extension C pour postgresql (à partir de 9.3) et une interface en Perl and Mojolicious. Un projet prometteur (bien que l'on puisse être supris qu'il soit écrit en Perl) pour maîtriser les performances de sa base de données postgresql.

http://www.logilab.org/file/266940/raw/safe.png

Enfin, Dimitri Fontaine a prêché la bonne parole pour rapprocher les développeurs des administrateurs de bases de données. L'idée était de faire penser aux développeurs que le SQL dans leur code est du code, pas juste des chaînes de caractères. Quelques exemples autour des "window functions" et de "common table expressions" plus tard, on espère que les développeurs feront une partie de leurs calculs directement dans PostgreSQL plutôt que dans leur application (en évitant de balader des tonnes de données entre les deux). Petit conseil : il est recommandé de rajouter des commentaires dans les requêtes SQL. "SQL c'est un language de programmation en vrai."

Les slides devraient être publiés sous peu sur le groupe meetup, que vous pouvez rejoindre pour être informés du prochain meetup. Update : slides publiés sur : https://wiki.postgresql.org/wiki/PostgreSQL_Meetup_Paris_2014_Sept

À Logilab nous utilisons beaucoup Postgresql que ce soit sur des projets clients (données métier, GIS, etc.) mais aussi extensivement dans CubicWeb, framework web en python orienté web sémantique.

Le format de 20 minutes par présentation est pas mal pour toucher rapidement à un grand nombre de sujets, du coup souvent il s'agit de pistes que chacun doit ensuite explorer. Les meetups sont toujours aussi sympathiques et accueillants.

[tarek] New Blog: Foule.es

Publié le 2014-10-08 21:09:00

Dear French reader. I have just launched a new blog in French about running.

=> http://foule.es <=

It'll probably talk about writing software from time to time, but it's basically about running.

[hautefeuille] Yify-pop dans un conteneur Docker

Publié le 2014-10-03 16:32:00

L’objectif de ce billet est de constituer un fichier Docker qui va construire un conteneur basé sur une Ubuntu 14.04, installer le logiciel Yify-pop et démarrer le serveur Nodejs. Il est nécessaire d’être déjà aguerri avec les commandes Docker.

Création du fichier Docker

On indique dans ce fichier Docker les actions suivantes :

  • On se base sur une image Ubuntu 14.04,
  • On met à jour la liste des paquets,
  • On met à jour le système,
  • On installe les paquets Nodejs,
  • On télécharge le logiciel Yify-pop,
  • On compile le logiciel,
  • On démarre le démon,
  • On expose les ports 4000 et 8889 de l’application.

Contenu du fichier yifydock :

FROM ubuntu:14.04
MAINTAINER Julien Hautefeuille <julien@hautefeuille.eu>
RUN apt-get update
RUN apt-get -y upgrade
RUN apt-get -y install npm
RUN apt-get -y install git
RUN cd /opt && git clone https://github.com/yify-pop/yify-pop.git
RUN npm -g install geddy
RUN npm -g install peerflix
RUN ln -s /usr/bin/nodejs /usr/bin/node
RUN cd /opt/yify-pop && npm install && geddy
EXPOSE 4000 8889

Construction de l’image

Lancer la commande de build :

docker build -t jhautefeuille/yify-pop:v1 https://raw.githubusercontent.com/jhautefeuille/dockerfiles/master/yify-pop/yifydock

Cette commande va construire le conteneur et le lancer.

Lancement du conteneur Yify-pop

Pour lancer l’application Yify-pop :

docker run -d --publish 4000:4000 --publish 8889:8889 jhautefeuille/yify-pop:v1

[afpyro] AFPyro à Mons (BE) - le 2 Octobre

Publié le 2014-10-02 00:00:00

English version at the end of this page.

Amis Pythonistes, notez la date du prochain AFPyro (et venez-y) !

Le prochain Apero Python Belgium se tiendra le jeudi 2 Octobre à Mons, lors de la Quizaine Numérique de Mons, du 27 septembre au 19 octobre.

En plus des habitués de l’AFPyro, nous accueillerons des débutants en Python afin de leur présenter la puissance du langage.

Vous pourrez ainsi participer à un des deux workshops proposés en parallèle :

  1. Pour les Pythonistes débutants, un workshop pour apprendre les bases de Python, puis pour construire une application Web avec Flask.

2. Pour les développeurs avancés, une initiation à AsyncIO, suivie d’un exemple concret d’une API REST/JSON asynchrone avec AsyncIO, aiohttp, aiorest et aiopg. Enfin, un benchmark sera réalisé afin de comparer les performances avec une API REST/JSON synchrone en Flask.

N’oubliez pas de prendre votre ordinateur portable si vous voulez participer au workshop.

Bien entendu (car c’est dans le nom), un apéro sera également organisé pendant l’événement.

Rendez-vous à partir de 18h30, à Co-nnexion, Espace de Coworking, 2b Rue des Archers, 7000 Mons.

Toutes les infos des prochains AFPyros en Belgique : Aperos Python Belgium


Dear Pythonista friends, write down in your agenda the date of the next AFPyro (and come to it) !

The next Aperos Python Belgium will take place on Thursday, October 2nd in Mons, during the Quizaine Numérique de Mons.

Not only the regulars of AFPyro are welcome. We are also pleased to meet the beginners who want learn Python.

Two workshops will be available:

  1. For the Python beginners, a workshop to learn Python basic, then to build a Web application with Flask.

2. For the advanced developers, a workshop around AsyncIO with a REST/JSON API example with AsyncIO, aiohttp, aiorest et aiopg. Finally, a benchmark will be made to compare performances with a synchronous REST/JSON API with Flask.

Don’t forget your laptop if you want to take part of a workshop.

Of course (it’s in the name), an “apéro” will be also organized throughout the event.

Meeting as from 18:30, at Co-nnexion, Espace de Coworking, 2b Rue des Archers, 7000 Mons.

Further informations about the next AFPyros in Belgium: Aperos Python Belgium

[hautefeuille] RaspberryPI, NAS Synology et NFS

Publié le 2014-10-01 15:13:00

Introduction

L’objectif de ce billet est d’installer le système de fichiers Raspbian sur un répertoire partagé d’un NAS Synology par l’intermédiaire du protocole NFS.

Cette installation permet de soulager la carte mémoire. Celle-ci n’est en fait nécessaire que pour le démarrage de la carte RaspberryPI.

Prérequis

Il faut disposer d’une carte mémoire avec le système Raspbian déjà installé et configuré. Internet regorge de tutoriels sur l’installation de Raspbian.

L’adresse ip du serveur NAS est 192.168.0.3, l’adresse ip de la carte RaspberryPI est 192.168.0.199.

Il faut disposer d’un réseau local rapide car les fichiers du sytème de la RaspberryPI transiteront par le réseau.

J’ai également pu remarquer des problèmes de connection NFS lorsqu’une MTU trop élevée était utilisée.

Je n’utilise donc pas les “Jumbo frame” dans la configuration réseau du NAS Synology.

MTU

Préparation du NAS Synology

On crée tout d’abord un répertoire partagé.

share

On autorise ensuite le partage par NFS, sans mapping, en lecture / écriture. Le dossier exporté par NFS est donc le suivant : /volume1/rasp0.

share

192.168.0.199 correspond à l’adresse ip de la carte RaspberryPI.

Préparation de la carte mémoire

Dans un premier temps, nous allons monter le partage réseau NFS sur la carte RaspberryPI puis nous allons copier le système de fichiers sur cet emplacement réseau.

sudo mount -t nfs -o rw 192.168.0.3:/volume1/rasp0 /mnt
cp -axv /. /mnt/.
cp -axv /dev/. /mnt/dev/.

Préparation des fichiers du partage réseau

On édite ensuite le fstab du partage réseau auquel on ôte le point de montage de la carte mémoire, ici il s’agit de /dev/mmcblk0p2.

proc            /proc           proc    defaults 0 0
/dev/mmcblk0p1  /boot           vfat    defaults 0 0
none            /tmp            tmpfs   defaults 0 0
none            /var/run        tmpfs   defaults 0 0
none            /var/lock       tmpfs   defaults 0 0
none            /var/tmp        tmpfs   defaults 0 0
192.168.0.3:/volume1/rasp0  /   nfs     rw       0 0

La dernière ligne de la configuration est facultative puisqu’on va renseigner également cette information dans le fichier de boot dans la suite de ce billet.

On édite le fichier /etc/network/interfaces du partage réseau pour y désactiver toute référence à du DHCP.

#iface eth0 inet dhcp

Préparation de la séquence de boot (fichier sur la carte mémoire)

On édite le fichier de la carte mémoire /boot/cmdline.txt.

On y ajoute des informations complémentaires sur la même ligne que la ligne d’origine. Si vous êtes en DHCP, mettez ip=dhcp.

root=/dev/nfs rootfstype=nfs nfsroot=192.168.0.3:/volume1/rasp0,udp,vers=3 smsc95xx.turbo_mode=N ip=192.168.0.199:192.168.0.3:192.168.0.1:255.255.255.0
  • 192.168.0.199 est l’adresse de la carte RaspberryPI,
  • 192.168.0.3 est l’adresse du NAS Synology avec le partage NFS,
  • 192.168.0.1 est l’adresse de la passerelle,
  • 255.255.255.0 est le masque réseau.

Vous pouvez enfin rebooter la carte RaspberryPI.

Optimisations

Enfin pour soulager la carte mémoire, nous allons bouger la swap de la carte mémoire vers un loop device à travers le réseau.

sudo apt-get remove --purge dphys-swapfile
sudo rm /var/swap
sudo rm /etc/init.d/dphys-swapfile
sudo update-rc.d dphys-swapfile remove

sudo dd if=/dev/zero of=/var/swap bs=1M count=1024
sudo losetup /dev/loop0 /var/swap
sudo mkswap /dev/loop0
sudo swapon /dev/loop0

On édite ensuite /etc/rc.local du partage réseau pour y rendre les changements permanents.

echo "swap settings"
sleep 2
losetup /dev/loop0 /var/swap
mkswap /dev/loop0
swapon /dev/loop0

Liens

[logilab] Lancement du blog de la communauté salt francaise

Publié le 2014-09-25 16:14:00

La communauté salt est bien vivante. Suite au meetup de septembre, elle s'est doté d'un petit site web :

http://salt-fr.afpy.org
http://www.logilab.org/file/266455/raw/Screenshot%20from%202014-09-25%2014%3A32%3A27.png

Nous éspérons pouvoir continuer à rassembler les enthousiasmes autour de salt lors de ces rendez-vous tous les 2 mois. J'ai donc publié le compte rendu du meetup sur ce site.

[afpyro] AFPyro à Lyon - mercredi 24 septembre

Publié le 2014-09-24 00:00:00

Un Afpyro aura lieu le mercredi 24 septembre à partir de 19h à l’Antre Autre - 11 rue Terme - 69001 Lyon.

Une présentation sur les docstrings sera donnée au cours de cette soirée.

L’Antre Autre est un lieu où nous pouvons discuter autour d’un verre, et, pour ceux qui le souhaitent, prendre un repas.

Pour se rendre à l’Antre Autre :

  • en métro : arrêt Hôtel de Ville
  • en bus : lignes C13 et C18 arrêt Mairie du 1er ou lignes 19, C14 et C3 à l’arrêt Terreaux
  • en vélo’v : stations Place Sathonay, Carmélites Burdeau, Place de la paix

[AFPy Salt-fr] Rencontres Salt à Mozilla Paris

Publié le 2014-09-22 22:00:00

Pour ce 4ème meetup parisien des utilisateurs de Salt, nous étions acceuilli dans le luxe des locaux de Mozilla Paris, merci à eux!

Pour la partie du public qui découvrait salt, Arthur Lutz de Logilab a fait une introduction à Salt.

Arthur Lutz

Cyril Lavier nous à présenté l'utilisation de Salt chez Webedia. Voici les slides : /presentations/webedia-salt.pdf.

Cyril Lavier

Paul Tonelli nous a présenté une utilisation de la mine salt pour gérer des fichier de zone automatiquement avec salt. Voici les slides: http://docs.logilab.org/salt_dns/

Feth Arezki de Majerti a présenté samba_report_module qui produit du json utilisé par le projet samba_report_html.

Feth Arezki

Nicolas Pierron nous a montré une autre facon de penser la gestion de configuration en nous présentant la distribution linux NixOS.

Nicolas Pierron

Forcément, nous avons fini la soirée autour d'une pizza payée par Logilab et quelques boissons fournies par Mozilla. Merci à eux !

Pizza!

Pour les prochains meetups n'oubliez pas le document collaboratif d'organisation sur lequel vous pouvez faire des propositions de présentations. Vous pouvez aussi voter pour la date du meetup de novembre 2014.

[AFPy Salt-fr] Annonce : Meetup Salt Paris - Septembre 2014

Publié le 2014-09-18 22:00:00

Voici notre petit sélection pour démarrer notre meetup de la semaine prochaine (mardi 23 septembre 2014 à 19h dans les locaux de de Mozilla Paris) :

  • Retour d’expérience déploiement Salt chez Webedia (Cyril Lavier - Webedia)
  • Génération de fichiers de zone internes par salt (Paul Tonelli - Logilab)
  • Construire du monitoring de serveurs avec Salt et du HTML/javascript (Feth Arezki - Majerti)

Si un certain nombre de personnes de l'assistance ne connaissent pas Salt, on pourra se charger d'une petite introduction (avec des vieux slides).

N'oubliez pas de vous inscrire sur http://framadate.org/u85rt2y3iz1krhys c'est important car Mozilla a besoin d'un nombre d'inscrits pour des questions de sécurité (et pour offrir à boire).

Pour rappel les locaux de Mozilla Paris c'est au :

16 Bis Blvd. Montmartre Paris 75009 France

[cubicweb] Handling dependencies between form fields in CubicWeb

Publié le 2014-09-17 15:50:00

This post considers the issue of building an edition form of a CubicWeb entity with dependencies on its fields. It's a quite common issue that needs to be handled client-side, based on user interaction.

Consider the following example schema:

from yams.buildobjs import EntityType, RelationDefinition, String, SubjectRelation
from cubicweb.schema import RQLConstraint

_ = unicode

class Country(EntityType):
    name = String(required=True)

class City(EntityType):
    name = String(required=True)

class in_country(RelationDefinition):
    subject = 'City'
    object = 'Country'
    cardinality = '1*'

class Citizen(EntityType):
    name = String(required=True)
    country = SubjectRelation('Country', cardinality='1*',
                              description=_('country the citizen lives in'))
    city = SubjectRelation('City', cardinality='1*',
                           constraints=[
                               RQLConstraint('S country C, O in_country C')],
                           description=_('city the citizen lives in'))

The main entity of interest is Citizen which has two relation definitions towards Country and City. Then, a City is bound to a Country through the in_country relation definition.

In the automatic edition form of Citizen entities, we would like to restrict the choices of cities depending on the selected Country, to be determined from the value of the country field. (In other words, we'd like the constraint on city relation defined above to be fulfilled during form rendering, not just validation.) Typically, in the image below, cities not in Italy should be available in the city select widget:

Example of Citizen entity edition form.

The issue will be solved by little customization of the automatic entity form, some uicfg rules and a bit of Javascript. In the following, the country field will be referred to as the master field whereas the city field as the dependent field.

So here the code of the views.py module:

from cubicweb.predicates import is_instance
from cubicweb.web.views import autoform, uicfg
from cubicweb.uilib import js

_ = unicode


class CitizenAutoForm(autoform.AutomaticEntityForm):
    """Citizen autoform handling dependencies between Country/City form fields
    """
    __select__ = is_instance('Citizen')

    needs_js = autoform.AutomaticEntityForm.needs_js + ('cubes.demo.js', )

    def render(self, *args, **kwargs):
        master_domid = self.field_by_name('country', 'subject').dom_id(self)
        dependent_domid = self.field_by_name('city', 'subject').dom_id(self)
        self._cw.add_onload(js.cw.cubes.demo.initDependentFormField(
            master_domid, dependent_domid))
        super(CitizenAutoForm, self).render(*args, **kwargs)


def city_choice(form, field):
    """Vocabulary function grouping city choices by country."""
    req = form._cw
    vocab = [(req._('<unspecified>'), '')]
    for eid, name in req.execute('Any X,N WHERE X is Country, X name N'):
        rset = req.execute('Any N,E ORDERBY N WHERE'
                           ' X name N, X eid E, X in_country C, C eid %(c)s',
                           {'c': eid})
        if rset:
            # 'optgroup' tag.
            oattrs = {'id': 'country_%s' % eid}
            vocab.append((name, None, oattrs))
            for label, value in rset.rows:
                # 'option' tag.
                vocab.append((label, str(value)))
    return vocab


uicfg.autoform_field_kwargs.tag_subject_of(('Citizen', 'city', '*'),
                                           {'choices': city_choice, 'sort': False})

The first thing (reading from the bottom of the file) is that we've added a choices function on city relation of the Citizen automatic entity form via uicfg. This function city_choice essentially generates the HTML content of the field value by grouping available cities by respective country through the addition of some optgroup tags.

Then, we've overridden the automatic entity form for Citizen entity type by essentially calling a piece of Javascript code fed with the DOM ids of the master and dependent fields. Fields are retrieved by their name (field_by_name method) and respective id using the dom_id method.

Now the Javascript part of the picture:

cw.cubes.demo = {
    // Initialize the dependent form field select and bind update event on
    // change on the master select.
    initDependentFormField: function(masterSelectId,
                                     dependentSelectId) {
        var masterSelect = cw.jqNode(masterSelectId);
        cw.cubes.demo.updateDependentFormField(masterSelect, dependentSelectId);
        masterSelect.change(function(){
            cw.cubes.demo.updateDependentFormField(this, dependentSelectId);
        });
    },

    // Update the dependent form field select.
    updateDependentFormField: function(masterSelect,
                                       dependentSelectId) {
        // Clear previously selected value.
        var dependentSelect = cw.jqNode(dependentSelectId);
        $(dependentSelect).val('');
        // Hide all optgroups.
        $(dependentSelect).find('optgroup').hide();
        // But the one corresponding to the master select.
        $('#country_' + $(masterSelect).val()).show();
    }
}

It consists of two functions. The initDependentFormField is called during form rendering and it essentially bind the second function updateDependentFormField to the change event of the master select field. The latter "update" function retrieves the dependent select field, hides all optgroup nodes (i.e. the whole content of the select widget) and then only shows dependent options that match with selected master option, identified by a custom country_<eid> set by the vocabulary function above.

[AFPy-Nantes] Un barcamp pour bien terminer l'été indien

Publié le 2014-09-14 22:00:00

Suite au succès du dernier meetup, et pour bien finir ce mois de septembre ensoleillé, nous sommes heureux de vous proposer un nouveau BarCamp, le mardi 30 septembre, 19 heure, à la Cantine numérique Nantaise.

Le concept sera de se retrouver autour de plusieurs ateliers, et de participer collectivement, chacun étant invité à présenter ses trouvailles, à poser ses questions, etc.

Que vous soyez pythoniste confirmé, ou simple curieux, le format du barcamp devrait donc répondre à vos attentes : la découverte, l'échange, le collaboratif.

Comme d'habitude, ceux qui le souhaitent pourront prolonger l'évènement autour d'un verre.

Pour vous inscrire à l'évènement, cliquez ici.

Pour vous tenir informé du contenu exact de l'évènement, ou pour faire part de vos suggestions, n'hésitez pas à vous inscrire à la liste de diffusion des pythonistes nantais.

Vous pouvez aussi nous rejoindre sur le chan IRC de l'AFPy Nantes. :)

[tarek] The Perfect Running App

Publié le 2014-09-14 17:05:00

Note

Most running applications out there are good enough for casual runners. This blog post is my tentative to describe what I would like to see in a running app for more serious practice.

I used a few running applications to track all my runs. Mostly the Nike+ app since this what naturally came with my Nike+ watch before I switched to a Garmin Forerunner 310XT.

Changing watch

From Nike+ to Garmin...

The app was a bit frustrating for many reasons and I thought that was because it's made for beginners, and that I was not the typical user anymore. I was not really interested in the provided metrics and was looking for better things.

When I switched to my new watch I though the app would be as good as the hardware. But no. What came as a surprise is that all the applications I have tried or looked at are not really better than Nike+. It looks like they are all aiming at casual runners.

But when you buy a expensive watch and do 5 trainings per week, you have some expectations.

I still wonder how come we don't have something better in a domain where anyone can understand the basics of what a good training session should be, by reading 2 or 3 running magazines. Unless you are doing crazy elite training with a whole staff, it's not rocket science.

And in my running club, even the very experienced runners use one of these apps and get frustrated. But it seems that no one expects these apps to be better than they are right now. The general consensus around me is: you can analyze your runs manually, the watch and its software will just help you get the raw data.

This is not good enough for me. I am very frustrated. I want to see if I am making any progress by using months of data - and this is not easy to do by hand.

SmashRun looks like a promising app but still misses a lot of what I am looking for. Since it's built by runners who seem passionate about building the right stuff, I got a pro account to encourage them. They have a voting system for new features, people that have a pro account can use.

However, I would like to write down in this blog post what I am exactly looking for and what I despise in a running app.

Of course this is what I want - but I am pretty sure that most seasoned runners would want something similar. Maybe it exists ? You should let me know.

Stop comparing Apples and Oranges

I think this is the worst feature all running apps have: they will tell you your average pace and your "progression". Some of them try to take a coach-like tone and tell you stuff like:

You're getting slow!

Jeez. Of course I am getting slow. I ran an interval run yesterday with a specific pace of 3'40/km and today I am doing a long run at a very slow pace because this is how you train !

pace over the week

Yeah the pace varies during the week. Nothing I can do with this chart here.

Global metrics that use all your recorded runs have no sense

You can't do this. That does not mean anything. Knowing that my yearly average pace is 4'45 does not mean anything.

You can't either really know what will be my estimate finish on a 5k using one of my long runs.

Performance Index

My estimated 5k finish time based on one long run. Of course it's completely wrong.

Also, the volume of trainings and kilometers you do really depends on what you're aiming at. Someone that is getting ready for a marathon will do at least 60km/week, and will take it easy the last week.

That would be a non-sense if you are getting ready for a 5k - But in most apps, the runner that prepares for the marathon will appear like a killer compared to the 5k runner. Tell this to the runners that are doing 16' on a 5k...

Gold Medal

I will soon lose my Gold medal since my 5 weeks training plan is over.

Anyways. My point is that the software should be smarter there. Every run needs to be classified in very specific groups to have any useful metrics on it. The most important ones are:

  • long runs
  • short interval runs
  • long interval runs
  • races

Long Runs

A long run is basically running at a lower pace for a longer time than usual. If you are getting ready for a 10k, you usually have one or two long runs per week, that will last for 1h to 1h30 tops.

The goal of those runs is to try to keep the same steady heart rate, and usually if the place where you are running is flat enough, the same pace.

A long run look like this:

Long run

The red zone is the HR drift.

There are several interesting things in this chart: you don't usually warmup when you do long runs. So the first portion of the run is a slow raise of your pace and heart rate until you've reached the targeted zone.

The quality of a long run is your ability to stick with the same heart rate for the whole session. Unless you are very careful and slow down a bit over time, there will be a slow, natural increase of your heart reate over time.

The most interesting metric in the case of a long run is to determine how flat your HR is, excluding the warmup section at the beginning.

A possible variation is to add a few strikes in the middle of your long runs. It makes it less boring. For example 2x2mn at 10k speed. It's important that these two strikes don't confuse the software that measures how flat your HR is.

Comparing long runs can be done by looking at;

  • how good you are at keeping the desired HR over time
  • how fast your heart is beating for a given pace as long as the circuit is flat enough and how this evolves over time.

Short Interval Run

If I do a short interval run, this is how things will go:

  • 30' warmup
  • 12x (45" at max speed, 30" slow)
  • 10' to cool down
Long run

The red line is the linear regression of the fast strikes.

We can ditch the warmup. It does not bring any interesting data besides the volume of training. The only interesting thing to do there is to make sure it was long enough. That varies between runners, but for short intervals, it's usually roughly as long as the intervals themselves.

Now for the intervals, a quality metrics is to check if they are all done at the same speed. It's quite common to start the series very fast and to finish slowly, completely burnt by the first strikes. This is not good! A good interval run is done at the same speed for all strikes (both fast and slow segments). A great interval run is done with a slightly faster speed for the last intervals.

A good metrics in this case is the linear regression of the pace for the fast segments then the slow segments. It should be flat or slightly increasing.

The ten last minutes are also very intesting: how fast your heart rate decreases over the ten minutes ? The faster the better.

Comparing interval runs between them can be done by checking how these metrics progress over time.

Long Interval Runs

Long interval runs are like the short ones. The only difference is that you can take into account your HR variation between strikes to see how good you are at decreasing your HR between each strike. A linear regression can be added there.

Race

A Race is a very specific run, and has its specific metrics. Usually, we tend to start too fast with the danger of getting in the red zone in the first kilometers.

This is the perfect 10k run:

Long run

A 10K run with a perfect negative split.

The first 5-6k are down 3-5 seconds slower than your target pace, and the end of the run 3-5 seconds faster. This is called a negative split. The last 500m should be as fast as you can.

So for races, what I want to find out is if I was able to do a negative split, if I did not start too fast and if I was able to sprint to the finish line.

This is also a set of metrics that can be compared from race to race over time.

The Impact of Temperature

I have a friend at the racing club that trained hard for 8 weeks for a marathon. He was aiming at 3h15mn and practiced accordingly. The day the race was there, we had a very unusual heat wave in France - 37ºC which is a lot for my area. He finished the marathon in 3h40 and was happy about his performance!

The bottom line is that the heat or the cold directly impact how we perform - and this varies a lot between individuals. In my dream running app, I want to correlate my results with the temperature.

I want all my predictions to have a ponderation (not sure that's how you say it in english ;)) with the temperature.

The Impact of Rest

How long did you rest since the last run ? How did it impact your performances ?

With this information and how fast your heart slows down after your training, we can detect overtraining and undertraining.

I know Polar has a bit of this in its latest software. It tells you how long you should rest before your next run. I wonder how they calculate this.

The Social Part

Last year I ran in San Franscisco near the bay bridge with my Nike+ watch and when I uploaded my run I was delighted to see that I did a 1 mile segment many people did.

Unfortunately, the only thing the app was able to tell me is that I was 365th in terms of pace and another ridiculous rank in terms of how many runs I did there.

This is so stupid. Where am I getting with this ? Becoming the Running Mayor of the Pier? :)

There's one thing that could be interesting in running apps when comparing your data with other people: group users by ages and by records.

I am 37 and my 10k record is around 38' - I don't really care to know how I perform on a weekly basis compared to an elite runner who does 31', or a more casual runner who does 50'.

What could be interesting though is to compare with people that are at my level or age and that are getting ready for the same race maybe ? or a race that's similar enough and close enough.

Conclusion

This blog post is just a brain dump - some ideas are pretty vague and I have not really talked about the UX of the Running Software.

But the bottom line is that if you don't just jog, and want to use a running application for serious training, what I have described is what I think is needed.

I hope Smashrun will go into that direction!

[cubicweb] CubicWeb roadmap meeting on September 4th, 2014

Publié le 2014-09-08 23:52:00

The Logilab team holds a roadmap meeting every two months to plan its CubicWeb development effort. The previous roadmap meeting was in July 2014.

Here is the report about the September 4th, 2014 meeting. Christophe de Vienne (Unlish) and Dimitri Papadopoulos (CEA) joined us to express their concerns and discuss the future of CubicWeb.

Versions

Version 3.17

This version is stable but old and maintainance will continue only as long as some customers will be willing to pay for it (current is 3.17.16 with 3.17.17 in development).

Version 3.18

This version is stable and maintained (current is 3.18.5 with 3.18.6 in development).

Version 3.19

This version is stable and maintained (current is 3.19.3 with 3.19.4 in development).

Version 3.20

This version is under development. It will try to reduce as much as possible the stock of patches in the state "reviewed", "awaiting review" and "in progress". If you have had something in the works that has not been accepted yet, please ready it for 3.20 and get it merged.

It should still include the work done for CWEP-002 (computed attributes and relations).

For details read list of tickets for CubicWeb 3.20.0.

Version 3.21

Removal of the dbapi, merging of Connection and ClientConnection, CWEP-003 (adding a FROM clause to RQL).

Version 4.0

When the work done for Pyramid will have been tested, it will become the default runner and a lot of things will be dropped: twisted, dead code, ui and core code that would be better cast into cubes, etc.

This version could happen early in 2015.

Cubes

New cubes and libraries

CWEPs

Here is the status of open CubicWeb Evolution Proposals:

CWEP-0002 full-featured implementation, to be merged in 3.20

CWEP-0003 patches sent to the review. . Champion will be adim.

Work in progress

PyConFR

Christophe will try to present at PyConFR the work he did on getting CubicWeb to work with Pyramid.

Pip-friendly source layout

Logilab and Christophe will try to make CubicWeb more pip/virtualenv-friendly. This may involve changing the source layout to include a sub-directory, but the impact on existing devs is expected to be too much and could be delayed to CubicWeb 4.0.

Pyramid

Christophe has made good progress on getting CubicWeb to work with Pyramid and he intends to put it into production real soon now. There is a Pyramid extension named pyramid_cubicweb and a CubicWeb cube named cubicweb-pyramid. Both work with CubicWeb 3.19. Christophe demonstrated using the debug toolbar, authenticating users with Authomatic and starting multiple workers with uWSGI.

Early adopters are now invited to jump in and help harden the code!

Agenda

Logilab's next roadmap meeting will be held at the beginning of november 2014 and Christophe and Dimitri were invited.