Quantcast
Channel: AFPy's Planet
Viewing all 3409 articles
Browse latest View live

[afpyro] AFPyro à Bruxelles (BE) et Lyon - mercredi 23 Octobre

$
0
0

Bruxelles

Pour ce premier AFPyro-BE de rentrée, nous aurons le plaisir d’assister à trois présentations :

  1. Laurent Peuch nous montrera les différents outils de debug en Python.
  2. Hugo Herter fera un retour d’expériences sur PyBrain (réseaux neuronaux).
  3. Nicolas Pettiaux nous présentera une application Django orienté restauration.

Enfin, nous plannifierons le covoiturage afin de se rendre à la PyCON-FR qui aura lieu le 26-27 octobre à Strasbourg.

Pour les intéressés, un repas est prévu après les présentations.

Comment s’inscrire ?

Via ce formulaire: http://framadate.org/studs.php?sondage=hdx5xtm8thpkv6u6

Quand ?

Mercredi 23 Octobre à partir de 19h.

Où ?

L’évènement aura lieu à l’ULB Solbosch, dans le batiment K, la salle 3.601: http://www.ulb.ac.be/campus/solbosch/plan.html

Lyon

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

Une présentation sera donnée sur Buildbot. Buildbot est un framework d’intégration continue qui permet de construire, tester et distribuer vos logiciels en utilisant le flux de travail que vous aurez choisi (et sans installer d’usine à gaz ;) ).

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

[afpyro] AFPyro à Strasbourg (FR) - samedi 26 octobre

$
0
0

Lors de la conférence annuelle PyconFR qui aura lieu à Strasbourg du 26 au 29 octobre, nous prévoyons de se remplir la pense avec des spécialités locales (bière et flammequiches ou Flammenküchen en local !).

Ça se passera le samedi 26 au soir, dans le caveau du restaurant “Au brasseur” , un lieu charmant, authentique et convivial dans lequel vous pourrez déguster les bières “maison” et peut-être assister à un brassage en direct !

Pour faire les réservations, nous avons besoin de votre confirmation de présence question de pouvoir nous organiser.

Vous pouvez vous inscrire en suivant ce lien

Les inscriptions seront closes mercredi 23, alors cliquez sec !

[Biologeek] Extimité et portée

$
0
0

Un des enjeux du réseau est que nous solidifions et identifions nombre de nos conversations avec un large public. J'aimerais parfois pouvoir dire sur les URIs publiés par l'intermédiaire d'un en-tête HTTP, ce contenu expire dans tant de minutes ou jours. Quelle fiction voulons-nous construire ? Quel tableau voulons nous organiser ?

Les indiscrétions douces, Karl Dubost

Karl s'interroge sur la durée de vie des publications, Loïc expérimente(ait ?) le fait de servir son blog uniquement sur son réseau local pour ses visiteurs physiques. J'y réfléchis depuis la publication de mes pensées que j'envisageais de faire disparaitre au fil des mois sans en avoir finalement eu le courage. Il serait même possible avec quelques lignes de JS/CSS de faire symboliquement rouiller une page.

Comment limiter la diffusion en termes de temps et d'espace des publications personnelles ?

Je posais récemment la question sur Twitter de savoir s'il existait des personnes qui restreignaient leur compte public à un nombre de followers donné et je n'ai eu aucun écho si ce n'est de l'incompréhension. Qui serait assez fou pour frustrer son égo ainsi ? J'y vois pourtant un intérêt non négligeable pour retourner vers une sphère extime, retrouver un cercle de convivialité sur un espace ouvert est finalement assez compliqué et peu de services en ligne arrivent à recréer ces (tiers-)lieux physiques. Il y a bien IRC mais il ne s'agit pas à proprement parler de publication mais plus de discussion.

J'avais également songé à diffuser des informations locales via une antenne wifi réduisant leur portée à l'échelle d'un quartier. Quelle richesse d'échanges permettrait de créer une commune en développant un réseau social hyper-local ? Et quelles conversations pourraient être engagées avec les communes environnantes ? Que produirait du pair-à-pairs avec une contrainte géographique ? Quelles rencontres inter-générationnelles pourraient être provoquées ?

Il y a énormément de choses à expérimenter dans le numérique et le Web à une échelle locale. Les collectivités territoriales se jettent sur l'OpenData mais il y a tellement à créer sans céder à la facilité de reproduire ce qui ne marche pas ailleurs…

[afpyro] AFPyro à Lyon - mercredi 27 Novembre

$
0
0

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

Une présentation sera donnée sur le machine learning en Python (régression, clustering & classification).

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

[Biologeek] Premier regard

$
0
0

Quelques flocons qui atténuent des contractions,
Une voiture enneigée pour se rendre à la maternité.
Des mesures, des conseils, des murmures, un choix,
Quelques longues minutes de stress et te voilà.

Un cri puis le silence ; presque oppressant,
Un regard et tout s'arrête ; il est vivant.
Découvrir ce monde, un clignement après l'autre,
Fixer mes parents et refléter leurs doux sourires.

Premier hoquet, premières tétées, respirer, dormir,
Tant de sensations à explorer en étant bien accompagné,
Et de personnes à rencontrer pour apprendre à aimer.

Alexandre, bienvenue dans ce monde petit bonhomme,
Il nous reste tant à faire et à apprendre ensemble,
Tu as fait de moi un père, je ferai de toi un Homme.

[No] Un calendrier de l'avent de calendriers

$
0
0

Les plus perspicaces d'entre vous l'auront remarqué, j'ai démarré un nouveau projet récemment, hébergé sur Github. Avec la gentille permission de mes chefs, ce projet est open-source et à peu près n'importe qui est susceptible de contribuer et m'aider. Et si je dis que tout le monde y est convié, c'est aussi parce que ce projet peut concerner tout le monde.

Mais laisse-moi t'expliquer l'idée derrière ce projet : pour une application (construite à partir du fantastimagique framework Django) développée dans le cadre de mon travail, nous avions besoin d'une bibliothèque pour calculer des dates. Mais pas uniquement des dates calendaires, mais des dates qui prenaient en compte les jours ouvrés / fériés, les weekends, etc (et pour le moment, les dates françaises, essentiellement, mais pas que).

J'ai fait quelques recherches, et hormis un projet très intéressant appelé sobrement holidays, je n'ai pas vraiment trouvé de bibliothèque qui me convenait. D'autres bibliothèques ne se concentraient que sur un seul pays et ne permettaient pas de composer de variantes.

Donc voici... Workalendar. Workalendar est une bibliothèque Python, publiée sous licence MIT.

Workalendar fournit :

  • un jeu de classes Calendar pour définir les jours fériés fixes (comme le 1er Janvier ou le 14 juillet),
  • des méthodes pour calculer les jours fériés variables, basés sur la date de Pâques, le calendrier lunaire ou des calculs plus spécifiques (çàd. "le 3ème lundi du mois"),
  • des méthodes pour ajouter des jours ouvrés à une date donnée, ou tester si une date est ouvrée ou fériée.

Jusqu'ici, assez peu de calendriers ont été intégrés à workalendar.

Alors voilà l'idée...

À partir du 1er Décembre jusqu'à la veille de Noël, je vais essayer d'intégrer et de publier un calendrier par jour sur le dépôt Github. Ce sera un "calendrier de l'avent de calendriers".

Bien entendu, si tu as envie que j'ajoute un Calendrier dans la bibliothèque, tu peux adresser une "issue" Github et j'essaierai de faire tout mon possible pour l'ajouter pendant la période de l'avent.

Autrement, toute sorte de contribution ou de marque de soutien sera chaudement accueillie.

[Biologeek] Informatique plaisante

$
0
0

These are my rules and they make me happy. I hope they make you happy too. If you have computing rules of your own that make you happy, I encourage you to publish them.

al3x’s Rules for Computing Happiness

Listes découvertes en lisant celles de Vivek Haldar sur le même sujet. Je partage bien sûr certaines de ces réflexions mais je n'ai pas vraiment les mêmes priorités. J'avais commencé une liste sur le sujet et finalement tous les points convergeaient vers ces 2 principes pour que mon usage de l'informatique reste plaisant : simplifier et réduire.

Simplification des usages et réduction des outils. Ré-évaluation fréquente des outils utilisés et exploration de solutions plus simples. Certains outils me permettraient d'être plus productif mais leur apprentissage serait trop coûteux. D'autres ont beaucoup trop de fonctions pour que je puisse les utiliser sereinement. Utiliser des applications minimalistes transforme les usages.

Réduction des données et simplification des formats. Limiter les données stockées (mails, photos, archives, etc) est une façon de garder un système cohérent et sain. De limiter les recherches, les sauvegardes et les changements d'environnements. Conserver ses données dans un seul format (si possible ouvert et standardisé) est un gage de facilité de conversion le moment venu. La pérennité d'une donnée dépend de sa capacité à être transformée.

Il n'y a finalement que dans mon travail — même si j'ai choisi des langages comme Python ou JavaScript — que je n'arrive pas à suivre ces principes. Je trouve cela affreusement difficile de développer/tester/déployer les projets auxquels j'ai participé jusqu'à présent. Il faut que je travaille à rendre mes productions plus conviviales. Peut-être avec Docker ? Et si je proposais une image de ce site sous cette forme pour rendre sa consultation/sauvegarde distribuée ?

[Biologeek] Utilité et code

$
0
0

Je ne me souviens plus avec précision du moment où j'ai eu ce déclic. Peut-être suite à la non-utilisation de django-roa ou à la n-ième réécriture from scratch d'un projet sur lequel j'avais bossé pendant un an. Toujours est-il que le constat me semble clair aujourd'hui : le code que je produis a une durée de vie limitée. Et par limitée j'entends de l'ordre de quelques mois seulement en moyenne, peut-être moins si je compte les projets qui n'ont même pas été en production ou qui ont juste vivoté.

Forcément, une telle prise de conscience est brutale et remet en question l'utilité de son travail. Ce que je produis a si peu de valeur qu'il est jeté au bout de quelques mois ? Le Web est si futile que ses acteurs n'arrivent pas à en avoir une vision à moyen terme ? J'ai fini par en faire le deuil. Je produis du jetable qui peut accidentellement durer longtemps. Et cette approche permet de se concentrer sur les données et les liens, c'est la seule chose qui peut potentiellement rester après mon passage. Il est de ma responsabilité de les rendre réutilisables et c'est à travers ces indicateurs que je qualifie maintenant mon travail. La beauté du code a laissé place à une autre esthétique, celle des racines du Web.


[afpyro] AFPyro à Paris - le 13 Décembre

$
0
0

Venez discuter de votre langage de programmation favori autour d’un verre et plus si affinités.

Ouvert à toute personne intéressée, mais les trolls sont priés de laisser leur manteau poilu à l’entrée.

Quand ?

Le Vendredi 13 Décembre, vers 19h00.

Où ?

Café Chéri(e) (plan)

44 bd de la Villette, 75019 Paris (FR).

M°: Belleville /Colonel Fabien

[Biologeek] Sprints et randonnées

$
0
0

On parle régulièrement de sprints pour évoquer les itérations de développement ce qui va à l'encontre de l'Agile Manifesto qui milite pour un rythme de travail soutenable indéfiniment. Or, stricto sensu, on ne peut pas enchaîner plusieurs sprints. Quel autre terme imagé pourrait-on lui préférer ? Certains évoquent le jeu :

Le développement de logiciel est un « jeu collaboratif d’invention et de communication à ressources contraintes et à objectif fini » dans lequel les participants utilisent des marqueurs pour se souvenir, se stimuler et s’informer mutuellement dans chaque mouvement du jeu. Le premier but poursuivi est la « production » et le « déploiement » d’un système. Le second but est l’obtention d’un ensemble de marqueurs permettant d’être dans une position favorable pour engager le jeu suivant qui consiste à modifier le système existant ou à produire un système similaire. Les deux objectifs poursuivis simultanément sont en compétition vis-à-vis des ressources limitées.

Cooperative game manifesto for software development

La version longue de l'auteur sous la forme d'un résumé de présentation fait une analogie avec l'escalade :

Of all the comparison partners for software development that I have seen, rock climbing has emerged as the best. Here are some of the words and phrases that we can link with rock climbing. You can see how well they transfer to software development […]

Je lui préfère celle de la randonnée introduite par Stéphane lors de ParisWeb il y a 2 ans . On y retrouve l'entraînement, la technique, l'équipe, le matériel, la planification, le fun, les challenges, les ressources limitées tout en limitant la dangerosité (comparé à l'escalade).

L'inconvénient de la randonnée est qu'elle est encore trop individualiste, au mieux on se réparti la nourriture commune ou un peu de matériel au départ mais l'on n'a pas vraiment l'impression de réaliser quelque chose ensemble, pour le groupe.

Parenthèse : peut-être mieux qu'une randonnée, une transhumance ? :-)

Quand on passe son temps à enlever des problèmes, les gens oublient ceux qu’ils avaient avant et peuvent croire qu’il ne s’est rien passé […]

Mon activité ne change pas beaucoup. Je l’ai défini comme “chien de berger agile” : le mec qui courre partout, on se demande un peu ou il va, mais au final le troupeau atteint sa destination. Ce n’est pas moi qu’il faut suivre mais le résultat.

Profession chien de berger agile, Dimitri Baeli

On pourrait aller vers l'expédition, l'équipage ou la cordée mais cela ne fonctionne pas pour 2 raisons :

  • la notion de survie qui implique d'avoir un chef pour pouvoir prendre des décisions dans l'urgence lorsque des vies sont en jeu ;
  • la notion d'isolement qui a un impact psychologique très important sur l'équipe et qui accroit les tensions internes.

Finalement, le rythme soutenable tant convoité n'est-il pas utopique ? N'entretiendrait-il pas un certain confort qui limite la collaboration ? Comment entretenir itérations ET émulation au sein des équipes sans arriver à l'épuisement ?

[gvaroquaux] Publishing scientific software matters

$
0
0
Christophe Pradal, Hans Peter Langtangen, and myself recently edited a version of the Journal of Computational Science on scientific software, in particular those written in Python. We wrote an editorial defending writing and publishing open source scientific software that I wish to summarize here. The full text preprint is openly available in my publications list [...]

[cubicweb] Brainomics - A management system for exploring and merging heterogeneous brain mapping data

[cubicweb] Logilab's roadmap for CubicWeb on September 6th, 2013

$
0
0

The Logilab team holds a roadmap meeting every two months to plan its CubicWeb development effort. Here is the report about the Sept 6th, 2013 meeting. The previous report posted to the blog was the february 2013 roadmap.

Version 3.17

This version is now stable and maintained (release 3.17.7 is upcoming). It added a couple features and focused on putting CW to the diet by extracting some functionnalities provided by the core into external cubes: sioc, embed, massmailing, geocoding, etc.

For details read what's new in CubicWeb 3.17.

Version 3.18

This version is now freezed and will be published as soon as all the patches are tested and merged. Since we have a lot of work for clients until the end of the year at Logilab, the community should feel free to help (as usual) if it wants this version to be released rather sooner than later.

This version will remove the ldapuser source that is replaced by ldapfeed, implement Cross Origin Resource Sharing, drop some very old compatibility code, deprecate the old version of the multi-source system and provide various other features and bugfixes.

For details read list of tickets for CubicWeb 3.18.0.

Version 3.19

This version will probably be publish early next year (read january or february 2014) unless someone who is not working at Logilab takes responsibility for its release.

It should include the heavy refactoring work done by Pierre-Yves and Sylvain over the past year, that modifies sessions and sources to lay the path for CubicWeb 4.

For details read list of tickets for CubicWeb 3.19.0 or take a look at this head.

Squareui

Since Orbui changes the organization of the default user interface on screen, it was decided to share the low-level bootstrap related views that could be shared and build a SquareUI cube that would conform design choices of the default UI.

Logilab is now developping all its new projects based on Squareui 0.2. Read about it on the mailing list archives.

Mid-term goals

The mid-term goals include better REST support (Representational State Transfer), complete WSGI (Python's Web Server Gateway Interface) and the FROM clause for RQL queries (to reinvent db federation outside of the core).

Cubes

Our current plan is to extract as much as possible to cubes. We started CubicWeb many years ago with the Python motto "batteries included", but have since realized that having too much in the core contributes to making CubicWeb difficult to learn.

Since we would very much like the community to grow, we are now aiming for something more balanced, like Mercurial does. The core is designed such that most features can be developed as an extension. Once they are stable, popular extensions can be moved to the main library that is distributed with the core, and be activated with a switch in the configuration file.

Several cubes are under active development: oauth, signedrequest, dataio, etc.

Last but not least

As already said on the mailing list, other developers and contributors are more than welcome to share their own goals in order to define a roadmap that best fits everyone's needs.

Logilab's next roadmap meeting will be held at the beginning of November 2013.

[Biologeek] Voir un enfant

$
0
0

Voir un enfant s'éveiller,
Chaque jour un peu plus, chaque heure,
Et retrouver dans ses yeux la bienveillance et la naïveté originelles. L'incompréhension de ce monde aussi.

Voir un enfant rêver,
Un défilement de mimiques et de sursauts,
Et s'interroger sur l'inné et l'acquis en termes d'humanité. Sur la base de nos relations sociales aussi.

Voir un enfant hurler,
Ressentir l'impuissance et l'inutilité,
Et transmettre de la douceur pour apaiser la douleur. Absorber du stress pour l'évacuer par ailleurs.

Voir un enfant téter,
Fouissant, s'arc-boutant, s'épuisant,
Et se rappeler que nous sommes encore si proches de nos origines animales. De l'importance de l'éducation aussi.

Voir un enfant hoqueter,
De l'inconnu et de l'inconfort,
Et accepter les petits désagréments quotidiens. Mais savoir refuser les asservissements aussi.

Voir un enfant sourire,
Petite bulle de bonheur suspendue,
Et revoir ses priorités, ses démons, ses désirs. Avoir envie d'œuvrer pour un avenir plus radieux aussi.

Voir un enfant. Et retenir ses larmes…

[Biologeek] Baptême numérique

$
0
0

L'apprentissage commence très tôt, dès la première enfance. Volontairement ou pas, les siens le modèlent, le façonnent, lui inculquent des croyances familiales, des rites, des attitudes, des conventions, la langue maternelle bien sûr, et puis des frayeurs, des aspirations, des préjugés, des rancœurs, ainsi que divers sentiments d'appartenance comme de non-appartenance.

Et très tôt aussi, à la maison comme à l'école ou dans la rue voisine, surviennent les premières égratignures. Les autres lui font sentir, par leurs paroles, par leurs regards, qu'il est pauvre, ou boiteux, ou petit de taille, ou « haut-sur-pattes », ou basané, ou trop blond, ou circoncis, ou non circoncis, ou orphelin — ces innombrables différences, minimes ou majeures, qui tracent les contours de chaque personnalité, forgent les comportements, les opinions, les craintes, les ambitions, qui souvent s'avèrent éminemment formatrices mais qui parfois blessent pour toujours.

Les identités meurtrières, Amin Maalouf

Comment gérer l'identité numérique de son enfant ? Quelles protections mettre en place pour qu'il puisse jouir de son image le moment venu ? Quelle part d'intimité numérique lui préserver ?

Je me pose ces questions alors qu'il semble de plus en plus habituel de live-tweeter son accouchement ou de poster sur Facebook les premières mensurations. Je me pose ces questions alors qu'il n'y a plus suffisamment de respect au sein même de la famille pour ne pas diffuser des photos numériques car cela est devenu monnaie courante. Et je ne trouve de réponses que dans l'approche de certaines églises chrétiennes de procéder à un baptême puis à une confirmation lorsque l'enfant est en âge de faire ce choix. Je suis ouvert à toute autre piste non religieuse.

La réponse est peut-être démesurée mais la dérive actuelle me semble malsaine pour la construction de l'identité de mon fils, à peine né le voilà soumis au regard du global, de l'archivable et du traçable. Certaines expériences doivent rester à l'échelle des proches pour créer un univers « familial », qu'est-ce qu'un proche si ce n'est quelqu'un avec qui on a partagé des choses ? En rendant publics ces moments on détruit ces relations fortes, ce vécu commun, cette culture. On détruit une part de ce qu'il est et de ce qu'il deviendra en accélérant une rencontre.

J'ai envie que mon fils soit libre de choisir son appartenance à des communautés. Et qu'il interagisse avec elles de son propre gré. En étant accompagné s'il le souhaite. En faisant ses propres expériences aussi. J'ai envie qu'il puisse prendre le temps de découvrir ce nouveau lieu lorsqu'il se sentira prêt.


[carlchenet] Retour sur Brebis, le vérificateur automatisé de sauvegarde, aux JM2L

$
0
0
Suivez-moi aussi sur Identi.ca ou sur Twitter  Comme chaque année avait lieu à Sophia Antipolis les Journées Méditerrannéennes du Logiciel Libre, organisées par l’association Linux Azur. J’avais proposé pour cette année une présentation du projet  Brebis, le vérificateur automatisé de sauvegarde. C’était pour moi l’occasion de réaliser quelques slides parlant du projet (désormais disponible en ligne – CC by […]

[cyp] Introduction à la ZCA

$
0
0

La ZCA est ensemble de bibliothèque implémentant une série de design pattern :

  • interface,
  • registry,
  • factory,
  • adapter.

ZCA signifie Zope Component Architecture. La ZCA a été créé pour zope mais est utilisable sans difficulté en dehors de zope. Il ne faut surtout pas se laisser effrayer par le mote zope : la ZCA n'est pas zope. Il n'y a pas besoin de comprendre zope pour s'en servir.

Les design patterns

Les design patterns ou patron de conceptions sont une série de concepts de programation objet établie par le gang of four. Ces patrons sont des organisations de code ou de classes récurrentes dans la programtion objet.

Le gang of four en établit 23. Je ne vais pas les détailler ici mais seulement les quatre cités plus haut. Ces patrons ne sont pas spécifiques à un langage mais sont implémentables dans la plupart des langages objets.

Installation

Seuls deux packages sont nécéssaires : zope.interface et zope.component.

Via pip :

$ pip install zope.interface zope.component

Buildout :

[buildout]
parts =
       ZCA

[ZCA]
recipe = zc.recipe.egg
eggs =
      zope.interface
      zope.component

Interface

Utilisée seule, l'interface est le pattern le moins intéressant en python. Les interfaces sont très (voire trop) utilisées en Java.

Une interface est une classe abstraite (classe non instansciable ni héritable (sauf par une autre interface)) qui est un contrat pour les classes l'implémentant.

from zope.interface import Interface
from zope.interface import Attribute


class IDuck(Interface):
    """
    Duck description.
    """

    name = Attribute("name of the duck")

    def kwack():
        """
        Sound of a duck
        """

Ce code définit une classe IDuck (Une convention assez fréquente quelque soit le langage est de préfixer par un I.) qui est une interface. On définit ici qu'un canard doit avoir un nom et caquete.

Définisons deux especes de canards : cygne et colvert.

from zope.interface import Interface
from zope.interface import Attribute
from zope.interface import implementer


class IDuck(Interface):
     """
     Duck description.
     """

     name = Attribute("name of the duck")

     def kwack():
         """
         Sound of a duck.
         """


@implementer(IDuck)
class Swan(object):
     """
     Swan implementation of IDuck.
     """

     def __init__(self, name):
         self.name = name

     def kwack(self):
         print("swan kwack")


@implementer(IDuck)
class Mallard(object):
     """
     Mallard implementation of IDuck.
     """

     def __init__(self, name):
         self.name = name

     def kwack(self):
         print("Mallard kwack")


s = Swan('foo')
m = Mallard('baz')

for duck in [s, m]:
    print(duck.name)
    duck.kwack()

A l'usage cela donne :

$ bin/python interface.py
foo
swan kwack
baz
Mallard kwack

Sauf que grace au duck typing de python le code suivant produit exactement le même résultat.

class Swan(object):
     """
     Swan implementation of Duck.
     """

     def __init__(self, name):
         self.name = name

     def kwack(self):
         print("swan kwack")


class Mallard(object):
     """
     Mallard implementation of Duck.
     """

     def __init__(self, name):
         self.name = name

     def kwack(self):
         print("Mallard kwack")


s = Swan('foo')
m = Mallard('baz')

for duck in [s, m]:
    print(duck.name)
    duck.kwack()

So what ? Comme dit plus haut ça ne sert pas à grand chose en python... Un petit rappel sur le duck typing : « Si ça fait coin, c'est un canard. ». En python, il n'y a pas de typage statique. Les types ne comptent pas (ou très peu), Les méthodes et les attributs sont plus importants.

Avec la ZCA et contrairement à java, les interfaces sont un contrat entre developppeurs. Le premier s'engage à utiliser les méthodes d'une interface et le second à écrire une classe qui implémente cette interface. En java, c'est un contrat entre le code et le compilateur : si le contrat n'est pas respecté, le code ne compile pas.

Avec la ZCA, il n'y a pas de contrainte :

@implementer(IDuck)
class Cat(object):
     """
     Dude, this is a non sens !!!
     """

     def __init__(self, name):
         self.name = name

s = Swan('foo')
m = Mallard('baz')
c = Cat('bar')

for duck in [s, m, c]:
    print(duck.name)
    duck.kwack()

et donc à l'exécution :

$ bin/python interface.py
foo
swan kwack
baz
Mallard kwack
bar
Traceback (most recent call last):
  File "bin/python", line 78, in <module>
    execfile(__file__)
  File "/tmp/interface.py", line 58, in <module>
    duck.kwack()
AttributeError: 'Cat' object has no attribute 'kwack'

On peut implémenter une interface sans la respecter. Ce n'est pas très pertinent mais possible. L'interface ne sert que de contrat et de documentation.

Utilisée seule l'interface ZCA n'apporte rien à part ajouter un tas de lignes inutiles.

Les registres

Les registres (voire plutôt le registre) ne sont pas un pattern du GoF. Un registre est un singleton (lui c'est un design pattern) qui mémorise l'instance d'autres classes.

class Registry(object):
     _instance = None

     def __new__(cls):
         if cls._instance is None:
             cls._intance = Registry()
         return cls._instance

     def __init__(self):
         self._memory = {}

    def save(self, name, instance):
        self._memory[name] = instance

    def get(self, name):
        return self._memory[name]


reg1 = Registry()
reg2 = Registry()

print(reg2 is reg1)

Nous avons ici une classe qui n'est instanciée qu'une seule fois et qui nous permet de sauver des objets puis de les récupérer. Ce mécanisme est intéressant si l'on utilise des objets couteux à intancier et très rapide à utiliser. Dans mon boulot, je travaille beaucoup sur des fichiers xmls que je dois valider à l'aide d'une grammaire (xsd le plus souvant). La construction de l'outil de validation prends un temps certain.

from glob import iglob
from lxml import etree

# ces 2 lignes coutent
xsdRoot = etree.parse(pathToXsdFile)
xsd = etree.XMLSchema(xsdRoot)

for xml in iglob("*.xml"):
    root = etree.parse(xml)
    print(xsd.validate(root))

Ce code représente un cas idéal où tous les xml sont au même endroit et en même temps. Dans une version plus proche de la réalité, les xmls sont servis par un webservice qui doit répondre le plus vite possibe.

Dans un __init__.py, on aurait le code suivant :

reg = Registry()
reg.save('xsd', xsd) # le xsd de notre bloc de code précédent.

et dans le fichier views.py :

# récupération du xml à valider plus dans un code imaginaire avant

reg = Registry()
xsd = reg.get('xsd')

return xsd.validate(xml)

Une autre solution à ce problème aurait été de faire un singleton avec cette xsd mais si on a besoin d'une autre classe de ce genre il faut refaire un singleton. De plus, on pourrait avoir plusieurs types de grammaires avec chacun leur xsd associée et on ne peut plus faire un singleton dans ce cas la.

reg = Registry()
reg.save('xsd1', xsd1)
reg.save('xsd2', xsd2)
reg.save('xsd3', xsd3)
reg = Registry()
xsd = reg.get(request.POST['xsd'])

return xsd.validate(xml)

Revenons à la ZCA, celle-ci offre un registry[2] : le gsm. gsm signifie Global Site Manager. Le gsm peut mémoriser des objets selon une interface.

[2]C'est inexact : le GSM est un registry offert par la ZCA mais on peut très bien hériter de la classe zope.interface.registry.Components pour implémenter le sien.

Reprenons notre exemple de xsd (inspiré de mon job).

from zope.interface import Interface
from zope.interface import implementer
from zope.component import getGlobalSiteManager

# Créons une classe IValid
class IValid(Interface):
    def validate(document):
        """
        Validate a document.
        """

# puis notre classe de validation
@implementer(IValiad)
class Xsd(object):
    def __init__(self, xsdfile):
        xsdRoot = etree.parse(pathToXsdFile)
        self._xsd = etree.XMLSchema(xsdRoot)

   def validate(document):
       """
       Validate a document.
       """
       return self._xsd.validate(document)


xsd = Xsd('/path/to/gramar.xsd')

gsm = getGlobalSiteManager()
gsm.registerUtility(xsd, IValid)

Et dans un lointain fichier :

from zope.component import getUtility

xsd = getUtility(IDuck)

xsd.validate(someDocument)

Avec ce mécanisme, on ne peut récupérer qu'un seule instance de Xsd ce qui n'apporte rien par rapport à un singleton. L'intérêt est d'avoir des instances différentes pour chacune des grammaires que l'on manipule.

gsm = getGlobalSiteManager()

xsd1 = Xsd('/path/to/gramar1.xsd')
gsm.registerUtility(xsd1, IValid, 'gramar1')

xsd2 = Xsd('/path/to/gramar2.xsd')
gsm.registerUtility(xsd2, IValid, 'gramar2')

xsd3 = Xsd('/path/to/gramar3.xsd')
gsm.registerUtility(xsd3, IValid, 'gramar3')

Si l'on reprend l'exemple plus haut :

from zope.component import getUtility

xsd = getUtility(IValid, request.POST['grammar'])

return xsd.validate(document)

Le registry nous permet de sauver des instances pour les utiliser plus tard. C'est un outil extrèmement pratique mais il faut le réserver aux objets dont la construction est coûteuse. Un usage abusif du registry va transformer votre code en code spagetti. Un inconveniant majeur de cet outil est qu'on perd la notion d'import de nos parties métiers.

Les factories

Une factory est une classe[1] qui instancie une autre classe.

[1]Le GoF définit cela comme une méthode. La zca, comme beaucoup, a définit la factory comme une classe.
class Duck(object):
     """
     This is a  duck.
     """

     def __init__(self, name):
          self.name = name


class FactoryDuck(object):
    """
    This is an egg ?
    """
    def __call__(self, name):
        """
        Lets make a duck.
        """
        return Duck(name)


fd = FactoryDuck()
duck = fd('foo')

print(type(duck))
print(duck.name)
$ bin/python /tmp/factory.py
<class '__main__.Duck'>
foo

Une factory sert à déporter l'instanciation d'un objet à une autre classe pour plusieurs raisons comme :

  • on appelle fréquement une classe qui a tendance à changer de chemin au fil de ses versions,
  • lors de l'écriture du code, on ignore la classe à instancier (ex: la connexion à une base donnée).

Explorons le premier cas. C'est un pis-aller à un mauvais problème. Notre code utilise un code tier qui à tendance à changer d'arborescence. Ce code est fourni par le pypi, par un fournisseur avec qui il faut utiliser un protocole proprio dont il faut utilise le code fourni. Bref un cas ou on est contraint d'utiliser un code mouvant.

Dans la première version, la classe Connection est dans fournisseur.class, dans la seconde, le fournisseur a lu un bouquin sur java et donc la classe se trouve dans com.fournisseur.class et dans une troisième version fournisseur.classes.connector etc, etc. L'effet de bord de cette promenade est qu'il faut repasser dans tous nos fichiers appelant ce code pour corriger.

Une solution est d'utiliser une factory[3] pour palier en partie à ce problème.

# cet import est soumis au bon vouloir du fournisseur
from fournisseur.classes.connector import Connection

class FactoryConnection(object):
    def __call__(self, *args, **kwargs):
        return Connection(args, kwargs)
[3]Ici la factory est une classe mais cela pourrait être une méthode. J'utilise ici une classe par goût et par habitude.

Puis dans notre code, on utilise partout cette factory pour ne pas réécrire en permanence nos imports mais seulement un dans la definition de la factory.

instance = FactoryConnection(args1, args2, kwargs1='value1')

On aurait également pu faire un héritage pour résoudre ce problème. C'est une solution à un mauvais problème. Je mentionne cet usage qui n'est pas très courant mais il peut arriver qu'on le croise.

L'usage plus courant (et plus sain) est le cas où l'on ignore la classe à instancier lors de l'écriture du programe. L'exemple typique est la connexion à la base de données dans un ORM comme SQLAlchemy.

Lorsque le programme est écrit on ignore (volontairement parfois) le SGBD qui sera utilisé lors du déploiement. Lors du lancement, le connecteur au SGBD utilise une factory pour savoir quelle classe de connexion à la base de données utiliser.

Imaginons qu'on doive décompresser des archives zip ou tar selon le type de fichier.

import os.path
from zipfile import ZipFile
from tarfile import TarFile


class FactoryArchive(object):
    """
    Build Archive.
    """
    _choices = {'zip': ZipFile,
               'tar': TarFile}

    def __call__(self, filename):
        """
        Return the correct class.
        """
        _, ext = os.path.splitext(os.path.basename(filename))
        return self._choices[ext.lower()](filename, mode='r')

L'usage du code serait le suivant :

# filename is something like /foo/bar/baz.tar or /foo.bar.baz.zip

factory = FactoryArchive()
archive = factory(filename)

archive.extractall('/tmp')

À l'écriture du code, on ignore si TarFile ou ZipFile seront appelés [4]

[4]Ici le code va planter lamentablement sur foo.tar.bz2 car le cas n'est pas géré. Il convient de prévoir les exceptions pour gérer ces cas.

La ZCA contient déja une classe Factory qui implémente une classe IFactory.

# factories for build ZipFile or TarFile.
from zipfile import ZipFile
from tarfile import TarFile

from zope.component.factory import Factory

factoryZip = Factory(ZipFile, 'zip')
factoryTar = Factory(TarFile, 'tar')

Et à l'usage :

import os.path

choices = {'zip': factoryZip,
          'tar': factoryTar}

_, ext = os.path.splitext(os.path.basename(filename))

factory = choices[ext.lower()]
archive = factory(filename)

archive.extractall('/tmp')

Jusque là cela ne réduit pas beaucoup le code ni le simplifie vraiment. Couplé au gsm vu plus haut les choses commencent à devenir plus intéressantes.

# factories for build ZipFile or TarFile.
from zipfile import ZipFile
from tarfile import TarFile

from zope.component.interfaces import IFactory
from zope.component import getGlobalSiteManager
from zope.component.factory import Factory

factoryZip = Factory(ZipFile, 'zip')
factoryTar = Factory(TarFile, 'tar')

gsm = getGlobalSiteManager()

gsm.registerUtility(factoryZip, IFactory, 'zip')
gsm.registerUtility(factoryTar, IFactory, 'tar')

Ce qui devient à l'usage :

import os.path

from zope.component import getUtility
from zope.component.interfaces import IFactory

_, ext = os.path.splitext(os.path.basename(filename))

factory = getUtility(IFactory, ext)
archive = factory(filename)

archive.extractall('/tmp')

On ne réduit pas le nombre de lignes de façon significative mais on réduit l'écriture de code complexe qu'on écrit soit même pour le déléguer à la ZCA.[5]

[5]Dans cet exemple, on ignore complètement qu'on utilise factoryZip ou factoryTar. Cela peut-être à double tranchant et faire du code spagetti.

La classe Factory implémente l'interface IFactory. On peut écrire soit même des classes factory l'implémentant.

from zipfile import ZipFile
from tarfile import TarFile

from zope.component.interfaces import IFactory
from zope.component import getGlobalSiteManager
from zope.interface import implementer

@implementer(IFactory)
class ArchiveFactory(object)
    _choices = {'zip': ZipFile,
               'tar': TarFile}

    def __call__(self, filename):
        """
        Return the correct class.
        """
        _, ext = os.path.splitext(os.path.basename(filename))
        return self._choices[ext.lower()](filename, mode='r')


gsm = getGlobalSiteManager()
gsm.registerUtility(ArchiveFactory(), IFactory, 'archive')

Ce qui devient à l'usage :

from zope.component import getUtility
from zope.component.interfaces import IFactory

factory = getUtility(IFactory, 'archive')
archive = factory(filename)

archive.extractall('/tmp')

Les adaptateurs

Les adapters sont des classes qui présentent une classe implémentant une interface en présentant une autre.

Une classe Foo ne sait manipuler que des IBar mais on n'a sous la main que BazA et BazC qui implémentent tout deux IBaz.

from zope.interface import Interface
from zope.interface import implementer
from zope.interface import adapater


class IBar(Interface):
     """
     Interface IBar.
     """
     def bar():
         """
         Method bar.
         """

class IBaz(Interface):
     """
     Interface IBaz
     """

     def foo1(arg1):
         """
         First action.
         """

    def foo2():
        """
        And the second one.
        """


 @impleteter(IFoo)
 class Baz1(object):
     def foo1(self, arg1):
         self.arg1 = arg1

     def foo2(self):
         print('Baz1', self.arg1)

 @impleteter(IFoo)
 class Baz2(object):
     def foo1(self, arg1):
         self.arg1 = arg1

     def foo2(self):
         print('Baz2', self.arg1)

@adapater(IFoo)
@impleteter(IBar)
class AdapaterFoo(object):
    """
    """
    def __init__(self, baz):
        self._baz = baz

    def baz(self):
        self._baz.foo1("default args")
        self._baz.foo2()


#registering the adapater
gsm = getGlobalSiteManager()
gsm.registerAdapter(AdapaterFoo, name='adapt foo')

Nous avons donc créé deux interfaces, classes et un adapteur. Si on veut ce servir de ce code cela donnera ceci :

from zope.component import getAdapter
# baz est un objet Baz1 ou Baz2
# barUSer est un objet utilisant des IBar

adapte = getAdapter(baz, IBar)
# adapte est un AdapterFoo

barUser.set(adapte)
#[...]

Cet exemple est quelque peu abstrait et un peu long. Le point intéressant est que lorsque qu'une nouvelle classe implémentant IFoo sera créée il n'y aura aucun code supplémentaire à écrire pour s'en servir. Sans les adaptateurs, il aurait fallu écrire des classes spécifiques pour Baz1, Baz2 et toute autre nouvelle classe implémentant IFoo.

Mélangeons tout ça

Jusque ici tout mes exemples étaient assez abstraits, je vous en propose un plus constistant en mélangeant tout ce qu'on a vu précédement.

L'exemple est un programme qui va acquérir des archives, les décompresser, les modifier puis les stocker via différents services. Notre programme prendra ses instructions d'un fichier texte passé en argument.

Nous allons supposer que nos différentes parties viennent de différents composants déja écrits par des tiers ou pour d'autres projets.

La gestion des ftp et http se fera par une interface IRemote avec deux implémentations : http et ftp (ainsi qu'un abstract pour factoriser).

L'API simpliste spécifiée par l'interface IRemote nous permet de télécharger et d'uploader un fichier.

class IRemote(Interface):
    """
    Interface for handle remote file.
    """

    def get(filename):
        """
        Get a file.
        """

    def put(filename):
        """
        Upload a file.
        """


class AbstractRemote(object):
    def __init__(self, url):
        """
        Take an url as argument.
        """
        self._url = url


@implementer(IRemote)
class FTPRemote(AbstractRemote):
    def __init__(self, url):
        super(FTPRemote, self).__init__(url)
        self._ftp = FTP(self._url)

    def get(self, filename):
        self._ftp.login()
        self._ftp.retrbinary('RETR %s' % os.path.basename(filename),
                             open(filename, 'wb').write)
        self._ftp.close()

    def put(self, filename):
        self._ftp.login()
        self._ftp.storbinary('STOR %s' % os.path.basename(filename), 4,
                             open(filename, 'rb').read)
        self._ftp.close()


@implementer(IRemote)
class HTTPRemote(object):
    def get(self, filename):
        with open(filename, 'wb') as tmp:
            req = requests.get(self._url + '/' + os.path.basename(filename))
            tmp.write(req.read())

    def put(self, filename):
        with open(filename, 'rb') as tmp:
            files = {'data': tmp}
            requests.post(self._url + '/' + os.path.basename(filename), files)

Le composant suivant est la gestion des archives. Comme pour les accès distants, on adope une interface simpliste IArchive avec deux mréethodes : extractAll et compressAll.

class IArchive(Interface):
    """
    Inferface for handle compressed archive.
    """
    def extractAll(pathTo):
        """
        Exctract all file in dir pathTo.
        """

    def compressAll(pathFrom):
        """
        Compress all files from dir pathFrom.
        """


class AbstractArchive(object):
    def __init__(self, filename):
        self._filename = filename


@implementer(IArchive)
class ZipArchive(AbstractArchive):

    def extractAll(self, pathTo):
        with ZipFile(self._filename, 'r') as tmp:
            tmp.extractall(pathTo)

    def compressAll(self, pathFrom):
        with ZipFile(self._filename, 'w') as tmp:
            for todo in os.walk(pathFrom):
                tmp.write(todo, os.path.basename(todo))

@implementer(IArchive)
class TarArchive(AbstractArchive):

    def extractAll(self, pathTo):
        with TarFile(self._filename, 'r') as tmp:
            tmp.extractall(pathTo)

    def compressAll(self, pathFrom):
        with TarFile(self._filename, 'w') as tmp:
            for todo in os.walk(pathFrom):
                tmp.write(todo, os.path.basename(todo))

Et pour finir, puisées dans notre mirobolante bibliothèque de composants, les modifications à apporter aux contenus des fichiers.

class ITransform(Interface):

    def open(filename):

    def close():

    def transform(newName):

    filename = Attribute("filename")

class AbstractTransform(object):

    def open(self, filename):
        self._filename = filename
        self._content = open(self._filename, 'rb')

    def close(self):
        self._content.close()

    @property
    def filename(self):
        return filename

@implementer(ITransform)
class LowerTransform(AbstractTransform):

    def transform(self, newName):
        with open(newName, 'wb') as tmp:
            for line in self._content:
                tmp.write(line.lower())


@implementer(ITransform)
class UpperTransform(AbstractTransform):

    def transform(self, newName):
        with open(newName, 'wb') as tmp:
            for line in self._content:
                tmp.write(line.upper())

@implementer(ITransform)
class Rot13Transform(AbstractTransform):

    def transform(self, newName):
        import string
        rot13 = string.maketrans( "ABCDEFGHIJKLMabcdefghijklmNOPQRSTUVWXYZnopqrstuvwxyz",
                                  "NOPQRSTUVWXYZnopqrstuvwxyzABCDEFGHIJKLMabcdefghijklm")

        with open(newName, 'wb') as tmp:
            for line in self._content:
                tmp.write(string.translate(line, rot13))


@implementer(ITransform)
class Base64Transform(AbstractTransform):

    def transform(self, newName):
        import base64
        with open(newName, 'wb') as tmp:
            for line in self._content:
                tmp.write(base64.b64encode(line))

Tous ces composants sont pré-écrits pour des projets précédents ou sont écrits pour être utilisés dans d'autre projets dont les spécificités sont différentes du projet actuel. Il nous faudra enregistrer les factories de ces classes dans le gsm pour les utiliser plus tard.

Mais d'abord il nous faut désigner nos actions à l'aide d'une interface IAction.

class IAction(Interface):
    """
    Interface of action classes
    """
    def init(filename):
        """
        """

    def process(args):
        """
        """

Une fois IAction décrite, il suffit d'écrire la série d'adapters et de les enregistrer :

# Now we need adapters
gsm = getGlobalSiteManager()


@implementer(IAction)
@adapter(IRemote)
class AdapterGet(object):
    def __init__(self, adapte):
        self._adapte = adapte


    def process(self, arg):
        self._adapte.get(arg)


@implementer(IAction)
@adapter(IRemote)
class AdapterPut(object):
    def __init__(self, adapte):
        self._adapte = adapte


    def process(self, arg):
        self._adapte.put(arg)

gsm.registerAdapter(AdapterGet, 'get')
gsm.registerAdapter(AdapterPut, 'put')


@implementer(IAction)
@adapter(IArchive)
class AdapterExtract(object):
    def __init__(self, adapte):
        self._adapte = adapte

    def process(self, arg):
        self._adapte.extractAll(arg)


@implementer(IAction)
@adapter(IArchive)
class AdapterCompress(object):
    def __init__(self, adapte):
        self._adapte = adapte

    def process(self, arg):
        self._adapte.compressAll(arg)


@implementer(IAction)
@adapter(ITransform)
class AdapterTranform(object):
    def __init__(self, adapte):
        self._adapte = adapte

    def process(self, arg):
        tmp = tempfile.mkstemp()
        self._adapte.open()
        self._adapte.transform(tmp)
        self._adapte.close()

        os.move(tmp, self._adapte.filename)


gsm.registerAdapter(AdapterTranform)

On enregistre ensuite la série de factories. Les factories ne sont pas enregistrées par les composants mais dans notre programme. Cela permet de les nommer comme on le désire dans chaque programme.

ftpFactory = Factory(FTPRemote, 'ftp')
gsm.registerUtility(ftpFactory, IFactory, 'ftp')

httpFactory = Factory(HTTPRemote, 'http')
gsm.registerUtility(httpFactory, IFactory, 'http')

zipFactory = Factory(ZipArchive, 'zip')
gsm.registerUtility(zipFactory, IFactory, 'zip')

tarFactory = Factory(TarArchive, 'tar')
gsm.registerUtility(tarFactory, IFactory, 'tar')

Et parce que j'en ai marre, on factorise le truc.

# I'm bored, I refactore the next factories
for klass, doc in [(LowerTransform, 'lower'),
                   (UpperTransform, 'upper'),
                   (Rot13Transform, 'rot13'),
                   (Base64Transform, 'base64')]:
    factory = Factory(klass, doc)
    gsm.registerUtility(factory, IFactory, doc)

Et pour finir la partie spécifique de notre programme :

def splitInstruction(instruction):
    """
    """
    action, arg1, arg2 = instruction.split(' ')
    if '_' in action:
        return action.split('_'), arg1, arg2
    else:
        return action, ' ', arg1, arg2

instructions = open(sys.argvs[1])

for instruction in instructions:
    actionName, variante, arg1, arg2 = splitInstruction(instruction)

    factory = getUtility(IFactory, actionName)

    instance = factory()(arg1)

    if variante:
        action = getAdapter(instance, IAction, variante)
    else:
        action = getAdapter(instance, IAction)

    action.process(arg2)

Si on doit rajouter une classe qui implémente une interface que nous avons déja adaptée l'écriture du code devient très facile et très courte.

L'ajout d'une nouvelle classe Base64Decode qui implémente déja ITransform se résume à l'import de Base64Decode et l'ajout d'une factory pour Base64Decode.

factory = Factory(Base64Decode, 'base64decode')
gsm.registerUtility(factory, IFactory, 'base64decode')

De même pour une série de classes implémentant la même interface, il suffira d'écrire l'adapater et la série de factories.

Conclusion

La ZCA n'est pas spécifique à zope ou plone ; on la retrouve dans des projets comme pyramid ou twisted.

La ZCA oblige à penser sous forme de composants « agnostiques » et plus généralistes puis à les incorporer, les adaptant à nos applications métiers. À court terme, le processus est plus coûteux car il faut concevoir de façon générique mais à moyen terme et surtout à long terme le temps de développement se réduit beaucoup car on réutilise en permanence des composants déja écrits. Ces composants étant plus petits et plus mono taches sont faciles à tester.

Je n'ai pas tout abordé voici quelques pointeurs qui peuvent être utiles pour aller plus loin ou completer mes dires :

  • un article en anglais sur la ZCA,
  • sa traduction en français,
  • billet de blog du traducteur du lien précédent.

Merci à jpcw pour la relecture.

[Biologeek] Open-Source et solidarité

$
0
0

Je suis de plus en plus mal à l'aise avec le terme d'Open-Source. J'ai l'impression que l'on souhaite lui faire porter des valeurs qui sont très périphériques au fait de rendre du code source disponible. Pour moi l'Open-Source c'est de la solidarité entre développeurs. Pas plus. On peut y voir un nouveau modèle contributif qui va révolutionner la société ou le futur de nos interactions en pair à pair mais il ne faut pas oublier qu'il s'agit juste de solidarité entre personnes d'une même profession. Si l'on trouve tout cela exceptionnel c'est parce que la solidarité est de moins en moins présente dans nos relations quotidiennes (surtout professionnelles).

La solidarité nécessite de la communication et de la coopération pour pouvoir être effective mais ce sont des effets de bord. Elle conduit même à des rencontres et à des liens très forts avec le sentiment d'œuvrer pour quelque chose d'utile. Mais ça reste de la solidarité entre développeurs. Il n'y a pas de notion d'utilité sociale ou de plus grand dessein véhiculé par l'Open-Source. Et d'ailleurs ses effets dans ce cadre là sont minimes. En revanche, certaines sociétés exploitent à merveille cette solidarité sous couvert d'Open-Source. Pas forcément avec des objectifs humanistes…

Vous pouvez être fier(e) de faire de l'Open-Source, il s'agit de filer un coup de main à un pair, de co-apprendre et de mutualiser (ce qui est déjà pas mal). Mais vous n'êtes pas en train de sauver le monde pour autant :-).

[Biologeek] Tiers Lieux

$
0
0

Les Tiers Lieux sont :

  • COLLECTIF : Le Tiers-Lieu est un bien commun révélé, délimité, entretenu par et avec un collectif.
  • ESPACE : Sur un territoire identifié, le Tiers-Lieu est une interface ouverte et indépendante permettant l’interconnexion ainsi que le partage de biens et de savoirs.
  • TRAVAIL : Le Tiers-Lieu est un cadre de confiance où des individus hétérogènes se réunissent pour travailler et explorer des solutions dans une posture de coworking.
  • ORGANISATION : Le Tiers-Lieu favorise l’apparition de réseaux distribués d’acteurs en préservant un équilibre permanent entre individu et collectif, entre temps de travail et temps d’échange.
  • LANGAGE : Le Tiers-Lieu génère un langage commun et réappropriable entre des mondes différents et parfois contradictoire.
  • NUMÉRIQUE : Les outils et la médiation numérique facilitent l’apparition de situation de travail collective sur la constitution d’un patrimoine informationnel commun.
  • GOUVERNANCE : Le Tiers-Lieu développe une approche intelligente de la gouvernance grâce notamment à un rapport transformationnel avec les usagers-clients et aux licences libres.
  • SERVICES : Les services du Tiers-Lieu s'assemblent pour formaliser un environnement de consommation, de création, de production inédit et incarne ainsi une véritable culture de la transition économique.
  • FINANCEMENTS : Les modèles de financement des Tiers-Lieux se développent entre économie traditionnelle et contributive en se basant sur des partenariats publics, privés et personnels.
  • PROSPECTIVE : Le Tiers-Lieu est un processus exploratoire de valeurs à l’échelle humaine, sociétale et économique qui vise à devenir un élément central du fonctionnement de la cité.

Les Tiers Lieux, faites le(s) vous même !

Le manifeste des Tiers Lieux

Je vous invite à aller lire l'intégralité du manifeste qui donne une meilleure idée de ce qu'il y a derrière la notion de Tiers-Lieu. C'est Yoann Duriaux qui m'a initié à ce concept lors de Lift France en Octobre dernier qu'il résume ainsi sur son blog :

En faisant cohabiter localement des mondes différents et parfois contradictoires, le Tiers-Lieu enclenche un processus de rééquilibrage sur le territoire (territoire institué ou territoire projet). Il provoque un dialogue et des frictions, là où l’expertise clôt la discussion. Il invite à prendre possession, à faire évoluer, à explorer et à appliquer des solutions sur des problématiques jusqu’alors balisées. Qu’il soit question de gestion, de création, de production, de culture, de consommation, d’éducation, de famille, d’objets et de choses, il suggère une démarche de ré-appropriation de certains mécanismes sociaux. La démocratisation des technologies numériques a banalisé ce genre d’intervention. Elles trouvent dans les Tiers-Lieux un prolongement tangible. Ils en ont le même potentiel transformationnel, créatif, voire transgressif. C’est pour cette raison que le Tiers-Lieu est Tiers. Non pas à cause d’une position d’entre deux, mais parce qu’il ouvre sur de nouveaux champs.

Vivement maintenant !, Yoann Duriaux

Je suis récemment tombé aussi sur la notion de socialisme utopique et puis de lien en aiguille sur celle d'innovation frugale et enfin d'innovation sociale ouverte. Il y a quelque chose qui me plait bien dans tout cela mais ça demande encore un peu de maturation de ma part pour arriver à mixer. Et faire ensemble. Nous vivons une belle époque.

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

$
0
0

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

Une présentation sera donnée sur buildout. Buildout est un outil (écrit en Python) permettant de créer, assembler et déployer des applications à partir de plusieurs morceaux.

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
Viewing all 3409 articles
Browse latest View live