Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

added april fool post

  • Loading branch information...
commit d89223858a3fa8c47bec9b5207d63442df8467bf 1 parent aa20dd9
@n1k0 authored
Showing with 2,669 additions and 2,951 deletions.
  1. +2 −2 build/403.html
  2. +2 −2 build/404.html
  3. +2 −2 build/carnet/2010/back-from-djangocong-2010/index.html
  4. +2 −2 build/carnet/2010/choisir-son-metier/index.html
  5. +2 −2 build/carnet/2010/index.html
  6. +2 −2 build/carnet/2011/index.html
  7. +2 −2 build/carnet/2011/sudweb/index.html
  8. +10 −2 build/carnet/2012/index.html
  9. +4 −4 build/carnet/2012/nouveau-site/index.html
  10. +92 −0 build/carnet/2012/nouvelles-aventures/index.html
  11. +14 −2 build/carnet/feed/index.html
  12. +10 −2 build/carnet/index.html
  13. +47 −55 build/code/2010/about-rest-frameworks/index.html
  14. +52 −58 build/code/2010/custom-deployment-tasks/index.html
  15. +76 −108 build/code/2010/django-with-pip-virtualenv/index.html
  16. +53 −69 build/code/2010/express/index.html
  17. +2 −2 build/code/2010/index.html
  18. +27 −31 build/code/2010/pil-install/index.html
  19. +19 −29 build/code/2010/python-tab-completion/index.html
  20. +82 −94 build/code/2010/symfony-nginx-php-fpm/index.html
  21. +36 −48 build/code/2011/clever-settings/index.html
  22. +42 −48 build/code/2011/djt/index.html
  23. +2 −2 build/code/2011/index.html
  24. +133 −151 build/code/2011/scrape-and-test-any-webpage-using-phantomjs/index.html
  25. +10 −14 build/code/2011/setup-jenkins-github-private-repository-ubuntu/index.html
  26. +188 −224 build/code/2012/dead-easy-yet-powerful-static-website-generator-with-flask/index.html
  27. +24 −34 build/code/2012/gandi-standard-ssl-certificate-nginx/index.html
  28. +2 −2 build/code/2012/index.html
  29. +91 −107 build/code/2012/introducing-casperjs-toolkit-phantomjs/index.html
  30. +864 −1,054 build/code/feed/index.html
  31. +2 −2 build/code/index.html
  32. +2 −2 build/contact/index.html
  33. +451 −530 build/feed/index.html
  34. +53 −42 build/index.html
  35. +3 −3 build/photography/2009/climbers/index.html
  36. +3 −3 build/photography/2009/cross/index.html
  37. +3 −3 build/photography/2009/crossing-of-the-berezina-river/index.html
  38. +3 −3 build/photography/2009/dark-street/index.html
  39. +3 −3 build/photography/2009/euro/index.html
  40. +3 −3 build/photography/2009/fishers/index.html
  41. +3 −3 build/photography/2009/flying-home/index.html
  42. +2 −2 build/photography/2009/index.html
  43. +3 −3 build/photography/2009/last-chance-for-love/index.html
  44. +3 −3 build/photography/2009/last-cigarette/index.html
  45. +3 −3 build/photography/2009/mantis/index.html
  46. +3 −3 build/photography/2009/paris-night-light/index.html
  47. +3 −3 build/photography/2009/ray/index.html
  48. +3 −3 build/photography/2009/showoff/index.html
  49. +3 −3 build/photography/2009/smoke/index.html
  50. +3 −3 build/photography/2009/space-mountains/index.html
  51. +3 −3 build/photography/2009/steep/index.html
  52. +3 −3 build/photography/2009/thau-tot/index.html
  53. +3 −3 build/photography/2009/the-biker/index.html
  54. +3 −3 build/photography/2009/the-cyclop/index.html
  55. +3 −3 build/photography/2009/usual-puppets/index.html
  56. +3 −3 build/photography/2009/walking-shadows/index.html
  57. +3 −3 build/photography/2009/zebra-crossing/index.html
  58. +3 −3 build/photography/2010/angry-bird/index.html
  59. +2 −2 build/photography/2010/index.html
  60. +3 −3 build/photography/2010/kitesurfer/index.html
  61. +3 −3 build/photography/2010/soldes-en-arles/index.html
  62. +3 −3 build/photography/2010/sunny-plaza/index.html
  63. +3 −3 build/photography/2010/temple-of-consumption/index.html
  64. +3 −3 build/photography/2010/the-shadow/index.html
  65. +3 −3 build/photography/2010/timing-is-everything/index.html
  66. +3 −3 build/photography/2010/updown-side/index.html
  67. +3 −3 build/photography/2011/beach-boy/index.html
  68. +3 −3 build/photography/2011/blur/index.html
  69. +3 −3 build/photography/2011/bulls-raid/index.html
  70. +3 −3 build/photography/2011/cairn/index.html
  71. +3 −3 build/photography/2011/cloudy/index.html
  72. +3 −3 build/photography/2011/dolce-vita/index.html
  73. +2 −2 build/photography/2011/index.html
  74. +3 −3 build/photography/2011/moving-on/index.html
  75. +3 −3 build/photography/2011/ovation/index.html
  76. +3 −3 build/photography/2011/path/index.html
  77. +3 −3 build/photography/2011/presqu-ile-de-maguelone/index.html
  78. +3 −3 build/photography/2011/reading-desk/index.html
  79. +3 −3 build/photography/2011/reflections/index.html
  80. +3 −3 build/photography/2011/saint-guilhem-le-desert/index.html
  81. +3 −3 build/photography/2011/sandscape/index.html
  82. +3 −3 build/photography/2011/thau/index.html
  83. +3 −3 build/photography/2011/the-sheriff/index.html
  84. +3 −3 build/photography/2011/walkers-on-the-moon/index.html
  85. +3 −3 build/photography/2012/cadaques/index.html
  86. +3 −3 build/photography/2012/communism-is-dead/index.html
  87. +3 −3 build/photography/2012/dali-s-cadillac/index.html
  88. +3 −3 build/photography/2012/espiguette/index.html
  89. +3 −3 build/photography/2012/follow-the-black-dog/index.html
  90. +2 −2 build/photography/2012/index.html
  91. +3 −3 build/photography/2012/mystery-door/index.html
  92. +3 −3 build/photography/2012/presqu-ile-de-maguelone/index.html
  93. +3 −3 build/photography/2012/sunset-shooters/index.html
  94. +2 −2 build/photography/feed/index.html
  95. +2 −2 build/photography/index.html
  96. +12 −6 build/sitemap.xml
  97. +16 −3 build/static/css/style.css
  98. +1 −1  build/static/js/app.js
  99. +21 −9 build/static/less/style.less
  100. +1 −1  build/static/packed.css
  101. +2 −2 build/talks/2008/index.html
  102. +2 −2 build/talks/2008/methodes-et-processus-agiles/index.html
  103. +2 −2 build/talks/2009/30-symfony-best-practices/index.html
  104. +2 −2 build/talks/2009/index.html
  105. +2 −2 build/talks/2009/scrum-py/index.html
  106. +2 −2 build/talks/2010/django-pour-les-developpeurs-symfony-et-reciproquement/index.html
  107. +2 −2 build/talks/2010/index.html
  108. +2 −2 build/talks/2011/index.html
  109. +2 −2 build/talks/2011/integration-continue-projet-django/index.html
  110. +2 −2 build/talks/feed/index.html
  111. +2 −2 build/talks/index.html
  112. +15 −0 pages/carnet/2012/nouvelles-aventures.md
  113. +1 −1  requirements.txt
  114. +1 −1  static/packed.css
View
4 build/403.html
@@ -7,7 +7,7 @@
<title>Home | Nicolas Perriault</title>
<meta name="description" content="Nicolas Perriault's homepage.">
<meta name="viewport" content="width=device-width">
- <link rel="stylesheet" type="text/css" href="/static/packed.css?1331882038">
+ <link rel="stylesheet" type="text/css" href="/static/packed.css?1333283939">
<link rel="alternate" type="application/rss+xml" href="/code/feed/" title="Code (RSS)">
<link rel="alternate" type="application/rss+xml" href="/photography/feed/" title="Photography (RSS)">
<link rel="alternate" type="application/rss+xml" href="/talks/feed/" title="Talks (RSS)">
@@ -55,7 +55,7 @@
<!-- /container -->
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js"></script>
<script>window.jQuery || document.write('<script src="js/libs/jquery-1.7.1.min.js"><\/script>')</script>
- <script type="text/javascript" src="/static/packed.js?1331882039"></script>
+ <script type="text/javascript" src="/static/packed.js?1333283940"></script>
<script src="//platform.twitter.com/widgets.js" charset="utf-8"></script>
</body>
</html>
View
4 build/404.html
@@ -7,7 +7,7 @@
<title>Home | Nicolas Perriault</title>
<meta name="description" content="Nicolas Perriault's homepage.">
<meta name="viewport" content="width=device-width">
- <link rel="stylesheet" type="text/css" href="/static/packed.css?1331882038">
+ <link rel="stylesheet" type="text/css" href="/static/packed.css?1333283939">
<link rel="alternate" type="application/rss+xml" href="/code/feed/" title="Code (RSS)">
<link rel="alternate" type="application/rss+xml" href="/photography/feed/" title="Photography (RSS)">
<link rel="alternate" type="application/rss+xml" href="/talks/feed/" title="Talks (RSS)">
@@ -56,7 +56,7 @@
<!-- /container -->
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js"></script>
<script>window.jQuery || document.write('<script src="js/libs/jquery-1.7.1.min.js"><\/script>')</script>
- <script type="text/javascript" src="/static/packed.js?1331882039"></script>
+ <script type="text/javascript" src="/static/packed.js?1333283940"></script>
<script src="//platform.twitter.com/widgets.js" charset="utf-8"></script>
</body>
</html>
View
4 build/carnet/2010/back-from-djangocong-2010/index.html
@@ -7,7 +7,7 @@
<title>De retour de Djangocong | Carnet | Nicolas Perriault</title>
<meta name="description" content="Nicolas Perriault's homepage.">
<meta name="viewport" content="width=device-width">
- <link rel="stylesheet" type="text/css" href="/static/packed.css?1331882038">
+ <link rel="stylesheet" type="text/css" href="/static/packed.css?1333283939">
<link rel="alternate" type="application/rss+xml" href="/code/feed/" title="Code (RSS)">
<link rel="alternate" type="application/rss+xml" href="/photography/feed/" title="Photography (RSS)">
<link rel="alternate" type="application/rss+xml" href="/talks/feed/" title="Talks (RSS)">
@@ -83,7 +83,7 @@
<!-- /container -->
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js"></script>
<script>window.jQuery || document.write('<script src="js/libs/jquery-1.7.1.min.js"><\/script>')</script>
- <script type="text/javascript" src="/static/packed.js?1331882039"></script>
+ <script type="text/javascript" src="/static/packed.js?1333283940"></script>
<script src="//platform.twitter.com/widgets.js" charset="utf-8"></script>
</body>
</html>
View
4 build/carnet/2010/choisir-son-metier/index.html
@@ -7,7 +7,7 @@
<title>Choisir son métier, arrêter de le (faire) subir | Carnet | Nicolas Perriault</title>
<meta name="description" content="Nicolas Perriault's homepage.">
<meta name="viewport" content="width=device-width">
- <link rel="stylesheet" type="text/css" href="/static/packed.css?1331882038">
+ <link rel="stylesheet" type="text/css" href="/static/packed.css?1333283939">
<link rel="alternate" type="application/rss+xml" href="/code/feed/" title="Code (RSS)">
<link rel="alternate" type="application/rss+xml" href="/photography/feed/" title="Photography (RSS)">
<link rel="alternate" type="application/rss+xml" href="/talks/feed/" title="Talks (RSS)">
@@ -199,7 +199,7 @@
<!-- /container -->
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js"></script>
<script>window.jQuery || document.write('<script src="js/libs/jquery-1.7.1.min.js"><\/script>')</script>
- <script type="text/javascript" src="/static/packed.js?1331882039"></script>
+ <script type="text/javascript" src="/static/packed.js?1333283940"></script>
<script src="//platform.twitter.com/widgets.js" charset="utf-8"></script>
</body>
</html>
View
4 build/carnet/2010/index.html
@@ -7,7 +7,7 @@
<title>Carnet | Nicolas Perriault</title>
<meta name="description" content="Nicolas Perriault's homepage.">
<meta name="viewport" content="width=device-width">
- <link rel="stylesheet" type="text/css" href="/static/packed.css?1331882038">
+ <link rel="stylesheet" type="text/css" href="/static/packed.css?1333283939">
<link rel="alternate" type="application/rss+xml" href="/code/feed/" title="Code (RSS)">
<link rel="alternate" type="application/rss+xml" href="/photography/feed/" title="Photography (RSS)">
<link rel="alternate" type="application/rss+xml" href="/talks/feed/" title="Talks (RSS)">
@@ -80,7 +80,7 @@
<!-- /container -->
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js"></script>
<script>window.jQuery || document.write('<script src="js/libs/jquery-1.7.1.min.js"><\/script>')</script>
- <script type="text/javascript" src="/static/packed.js?1331882039"></script>
+ <script type="text/javascript" src="/static/packed.js?1333283940"></script>
<script src="//platform.twitter.com/widgets.js" charset="utf-8"></script>
</body>
</html>
View
4 build/carnet/2011/index.html
@@ -7,7 +7,7 @@
<title>Carnet | Nicolas Perriault</title>
<meta name="description" content="Nicolas Perriault's homepage.">
<meta name="viewport" content="width=device-width">
- <link rel="stylesheet" type="text/css" href="/static/packed.css?1331882038">
+ <link rel="stylesheet" type="text/css" href="/static/packed.css?1333283939">
<link rel="alternate" type="application/rss+xml" href="/code/feed/" title="Code (RSS)">
<link rel="alternate" type="application/rss+xml" href="/photography/feed/" title="Photography (RSS)">
<link rel="alternate" type="application/rss+xml" href="/talks/feed/" title="Talks (RSS)">
@@ -72,7 +72,7 @@
<!-- /container -->
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js"></script>
<script>window.jQuery || document.write('<script src="js/libs/jquery-1.7.1.min.js"><\/script>')</script>
- <script type="text/javascript" src="/static/packed.js?1331882039"></script>
+ <script type="text/javascript" src="/static/packed.js?1333283940"></script>
<script src="//platform.twitter.com/widgets.js" charset="utf-8"></script>
</body>
</html>
View
4 build/carnet/2011/sudweb/index.html
@@ -7,7 +7,7 @@
<title>Du Sud avec du Web dedans, et réciproquement | Carnet | Nicolas Perriault</title>
<meta name="description" content="Nicolas Perriault's homepage.">
<meta name="viewport" content="width=device-width">
- <link rel="stylesheet" type="text/css" href="/static/packed.css?1331882038">
+ <link rel="stylesheet" type="text/css" href="/static/packed.css?1333283939">
<link rel="alternate" type="application/rss+xml" href="/code/feed/" title="Code (RSS)">
<link rel="alternate" type="application/rss+xml" href="/photography/feed/" title="Photography (RSS)">
<link rel="alternate" type="application/rss+xml" href="/talks/feed/" title="Talks (RSS)">
@@ -105,7 +105,7 @@
<!-- /container -->
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js"></script>
<script>window.jQuery || document.write('<script src="js/libs/jquery-1.7.1.min.js"><\/script>')</script>
- <script type="text/javascript" src="/static/packed.js?1331882039"></script>
+ <script type="text/javascript" src="/static/packed.js?1333283940"></script>
<script src="//platform.twitter.com/widgets.js" charset="utf-8"></script>
</body>
</html>
View
12 build/carnet/2012/index.html
@@ -7,7 +7,7 @@
<title>Carnet | Nicolas Perriault</title>
<meta name="description" content="Nicolas Perriault's homepage.">
<meta name="viewport" content="width=device-width">
- <link rel="stylesheet" type="text/css" href="/static/packed.css?1331882038">
+ <link rel="stylesheet" type="text/css" href="/static/packed.css?1333283939">
<link rel="alternate" type="application/rss+xml" href="/code/feed/" title="Code (RSS)">
<link rel="alternate" type="application/rss+xml" href="/photography/feed/" title="Photography (RSS)">
<link rel="alternate" type="application/rss+xml" href="/talks/feed/" title="Talks (RSS)">
@@ -32,6 +32,14 @@
<ul class="item-list" itemprop="blogPosts">
<li>
<h3>
+ <a itemprop="url" href="/carnet/2012/nouvelles-aventures/"><span itemprop="name">Nouvelles aventures</span></a>
+ | <time datetime="2012-04-01">2012-04-01</time>
+ </h3>
+ <p><q itemprop="description"><em>Cela fait quelques mois que je m&#39;interroge sur la pérennité de mon activité en temps qu&#39;indépendant, car force est de constater que la ...</em></q></p>
+ <hr>
+ </li>
+ <li>
+ <h3>
<a itemprop="url" href="/carnet/2012/nouveau-site/"><span itemprop="name">Nouveau site</span></a>
| <time datetime="2012-03-03">2012-03-03</time>
</h3>
@@ -72,7 +80,7 @@
<!-- /container -->
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js"></script>
<script>window.jQuery || document.write('<script src="js/libs/jquery-1.7.1.min.js"><\/script>')</script>
- <script type="text/javascript" src="/static/packed.js?1331882039"></script>
+ <script type="text/javascript" src="/static/packed.js?1333283940"></script>
<script src="//platform.twitter.com/widgets.js" charset="utf-8"></script>
</body>
</html>
View
8 build/carnet/2012/nouveau-site/index.html
@@ -7,7 +7,7 @@
<title>Nouveau site | Carnet | Nicolas Perriault</title>
<meta name="description" content="Nicolas Perriault's homepage.">
<meta name="viewport" content="width=device-width">
- <link rel="stylesheet" type="text/css" href="/static/packed.css?1331882038">
+ <link rel="stylesheet" type="text/css" href="/static/packed.css?1333283939">
<link rel="alternate" type="application/rss+xml" href="/code/feed/" title="Code (RSS)">
<link rel="alternate" type="application/rss+xml" href="/photography/feed/" title="Photography (RSS)">
<link rel="alternate" type="application/rss+xml" href="/talks/feed/" title="Talks (RSS)">
@@ -68,8 +68,8 @@
</aside>
<hr>
<nav>
-
-
+ <a class="prev" href="/carnet/2012/nouvelles-aventures/">Nouvelles aventures</a>
+ |
<a class="next" href="/carnet/2011/sudweb/">Du Sud avec du Web dedans, et réciproquement</a>
</nav>
</article>
@@ -99,7 +99,7 @@
<!-- /container -->
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js"></script>
<script>window.jQuery || document.write('<script src="js/libs/jquery-1.7.1.min.js"><\/script>')</script>
- <script type="text/javascript" src="/static/packed.js?1331882039"></script>
+ <script type="text/javascript" src="/static/packed.js?1333283940"></script>
<script src="//platform.twitter.com/widgets.js" charset="utf-8"></script>
</body>
</html>
View
92 build/carnet/2012/nouvelles-aventures/index.html
@@ -0,0 +1,92 @@
+<!doctype html>
+<html class="no-js" lang="fr">
+<head>
+ <meta charset="utf-8">
+
+ <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
+ <title>Nouvelles aventures | Carnet | Nicolas Perriault</title>
+ <meta name="description" content="Nicolas Perriault's homepage.">
+ <meta name="viewport" content="width=device-width">
+ <link rel="stylesheet" type="text/css" href="/static/packed.css?1333283939">
+ <link rel="alternate" type="application/rss+xml" href="/code/feed/" title="Code (RSS)">
+ <link rel="alternate" type="application/rss+xml" href="/photography/feed/" title="Photography (RSS)">
+ <link rel="alternate" type="application/rss+xml" href="/talks/feed/" title="Talks (RSS)">
+ <link rel="alternate" type="application/rss+xml" href="/carnet/feed/" title="Carnet (RSS)">
+ <link rel="alternate" type="application/rss+xml" href="/feed/" title="Everything (RSS)">
+ <!--[if lt IE 9]>
+ <script src="//html5shiv.googlecode.com/svn/trunk/html5.js"></script>
+ <![endif]-->
+</head>
+<body class="carnet ">
+ <!--[if lt IE 7]>
+ <p class="chromeframe">Your browser is <em>ancient!</em> Please <a href="http://www.quirksmode.org/upgrade.html">upgrade</a>.</p>
+ <![endif]-->
+ <div class="container">
+ <header class="main-title">
+ <h1><a href="/">Hi, I'm <strong>Nicolas.</strong></a></h1>
+ <small>I code stuff. I take photos. I write rants.</small>
+ </header>
+ <div class="contents">
+
+
+ <article lang="en" class="carnet" itemscope itemtype="http://schema.org/BlogPosting">
+ <link itemprop="url" href="/carnet/2012/nouvelles-aventures/">
+ <header>
+ <h2><a itemprop="name" href="/carnet/2012/nouvelles-aventures/">Nouvelles aventures</a></h2></header>
+
+ <section>
+ <p>Cela fait quelques mois que je m'interroge sur la pérennité de mon activité en temps qu'indépendant, car force est de constater que la conjoncture ne facilite pas mon approche initiale plutôt artisanale du développement Web.</p>
+<p>C'est pour cela que lorsque j'ai été contacté par <a href="http://oracle.com/">Oracle</a> pour un éventuel rachat d'<a href="http://akei.com/">Akei</a>, ma société, afin d'intégrer l'expertise autour de <a href="http://casperjs.org/">CasperJS</a>, je n'ai pu m'empêcher d'y voir un signe du destin m'invitant à remettre en questions un certain nombre de principes que je croyais miens jusqu'alors.</p>
+<p>En effet, j'ai toujours — de façon un peu naïvement idéologique il est vrai — voulu privilégier une approche humaniste du développement logiciel, favorisant les interractions humaines avant tout dans la perspective de faciliter la production de valeur ajoutée. À l'épreuve des faits, force a été de constater que sans une approche épaulée commercialement de l'industrialisation de la production logicielle, tout ceci est condamné à rester lettre morte dans nos sociétés toujours plus assujestties aux vigoureuses et motivantes pressions économiques de toutes parts, particulièrement des pays émergeants, offrant toujours plus pour de moins en moins cher…</p>
+<p>Aussi, j'integrerai dès lundi <a href="http://www.oracle.com/fr/index.html">Oracle France</a> en tant que Responsable du Pôle Régional de Dévelopement Stratégique et d'Innovation Web au sein des locaux parisiens de la société. J'en profiterai par conséquence pour quitter Montpellier et retrouver la dynamique capitale française, que je suis bien obligé de légitimer comme le seul véritable endroit où <em>les choses se font</em>, comme on dit.</p>
+<p>En ce qui concerne <a href="http://casperjs.org/">CasperJS</a>, le processus de réécriture en Java a été secrètement entamé depuis quelques semaines, et je pense pouvoir fournir dans les jours qui viennent une première version alpha exploitant l'incroyable puissance de l'<a href="http://www.oracle.com/technetwork/developer-tools/adf/overview/index.html">Oracle Development Framework</a>…</p>
+<p>… et de tout l'<a href="http://www.marseille-sympa.com/merou.jpg">ecosystème J2EE plus généralement</a>.</p>
+ </section>
+ <aside>
+ <p>
+ <span class="article-author" itemprop="author" itemscope itemtype="http://schema.org/Person">
+ <span itemprop="name">Nicolas Perriault</span> —
+ </span>
+ <time datetime="2012-04-01" itemprop="datePublished">2012-04-01</time>
+ — in <a href="/carnet/" itemprop="genre">Carnet</a>
+ — <a href="/carnet/2012/nouvelles-aventures/">Permalink</a>
+ — <a rel="license" href="http://creativecommons.org/licenses/by-sa/3.0/">License</a>.
+ </p>
+ </aside>
+ <hr>
+ <nav>
+
+
+ <a class="next" href="/carnet/2012/nouveau-site/">Nouveau site</a>
+ </nav>
+</article>
+
+
+ </div>
+ <nav class="sidebar">
+ <ul>
+ <li class="home"><a href="/" hreflang="en">Home</a></li>
+ <li class="code"><a href="/code/" hreflang="en">Code</a></li>
+ <li class="photography"><a href="/photography/" hreflang="en">Photography</a></li>
+ <li class="talks"><a href="/talks/" hreflang="en">Talks</a></li>
+ <li class="carnet"><a href="/carnet/" hreflang="fr">Carnet <span>fr</span></a></li>
+ <li class="contact"><a href="/contact/" hreflang="en">Contact</a></li>
+ </ul>
+ </nav>
+ <footer class="site-footer">
+ <p>
+ &copy; 2012 Nicolas Perriault
+ — <a href="https://twitter.com/n1k0">Tweet at me</a>
+ — <a href="https://github.com/n1k0">Get my code</a>
+ — <a href="http://500px.com/n1k0">Enjoy my pics</a>
+ — <a href="/contact/">Contact me</a>
+ </p>
+ </footer>
+ </div>
+ <!-- /container -->
+ <script src="//ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js"></script>
+ <script>window.jQuery || document.write('<script src="js/libs/jquery-1.7.1.min.js"><\/script>')</script>
+ <script type="text/javascript" src="/static/packed.js?1333283940"></script>
+ <script src="//platform.twitter.com/widgets.js" charset="utf-8"></script>
+</body>
+</html>
View
16 build/carnet/feed/index.html
@@ -5,10 +5,22 @@
<link>https://nicolas.perriault.net</link>
<description>Le petit coin d'aigreur sur la toile de Nicolas Perriault.</description>
<language>fr</language>
- <pubDate>Fri, 16 Mar 2012 08:14:10 +0000</pubDate>
- <lastBuildDate>Fri, 16 Mar 2012 08:14:10 +0000</lastBuildDate>
+ <pubDate>Sun, 01 Apr 2012 14:44:52 +0000</pubDate>
+ <lastBuildDate>Sun, 01 Apr 2012 14:44:52 +0000</lastBuildDate>
<item>
+ <title>Nouvelles aventures</title>
+ <link>https://nicolas.perriault.net/carnet/2012/nouvelles-aventures/</link>
+ <description>&lt;p&gt;Cela fait quelques mois que je m&#39;interroge sur la pérennité de mon activité en temps qu&#39;indépendant, car force est de constater que la conjoncture ne facilite pas mon approche initiale plutôt artisanale du développement Web.&lt;/p&gt;
+&lt;p&gt;C&#39;est pour cela que lorsque j&#39;ai été contacté par &lt;a href=&#34;http://oracle.com/&#34;&gt;Oracle&lt;/a&gt; pour un éventuel rachat d&#39;&lt;a href=&#34;http://akei.com/&#34;&gt;Akei&lt;/a&gt;, ma société, afin d&#39;intégrer l&#39;expertise autour de &lt;a href=&#34;http://casperjs.org/&#34;&gt;CasperJS&lt;/a&gt;, je n&#39;ai pu m&#39;empêcher d&#39;y voir un signe du destin m&#39;invitant à remettre en questions un certain nombre de principes que je croyais miens jusqu&#39;alors.&lt;/p&gt;
+&lt;p&gt;En effet, j&#39;ai toujours — de façon un peu naïvement idéologique il est vrai — voulu privilégier une approche humaniste du développement logiciel, favorisant les interractions humaines avant tout dans la perspective de faciliter la production de valeur ajoutée. À l&#39;épreuve des faits, force a été de constater que sans une approche épaulée commercialement de l&#39;industrialisation de la production logicielle, tout ceci est condamné à rester lettre morte dans nos sociétés toujours plus assujestties aux vigoureuses et motivantes pressions économiques de toutes parts, particulièrement des pays émergeants, offrant toujours plus pour de moins en moins cher…&lt;/p&gt;
+&lt;p&gt;Aussi, j&#39;integrerai dès lundi &lt;a href=&#34;http://www.oracle.com/fr/index.html&#34;&gt;Oracle France&lt;/a&gt; en tant que Responsable du Pôle Régional de Dévelopement Stratégique et d&#39;Innovation Web au sein des locaux parisiens de la société. J&#39;en profiterai par conséquence pour quitter Montpellier et retrouver la dynamique capitale française, que je suis bien obligé de légitimer comme le seul véritable endroit où &lt;em&gt;les choses se font&lt;/em&gt;, comme on dit.&lt;/p&gt;
+&lt;p&gt;En ce qui concerne &lt;a href=&#34;http://casperjs.org/&#34;&gt;CasperJS&lt;/a&gt;, le processus de réécriture en Java a été secrètement entamé depuis quelques semaines, et je pense pouvoir fournir dans les jours qui viennent une première version alpha exploitant l&#39;incroyable puissance de l&#39;&lt;a href=&#34;http://www.oracle.com/technetwork/developer-tools/adf/overview/index.html&#34;&gt;Oracle Development Framework&lt;/a&gt;&lt;/p&gt;
+&lt;p&gt;… et de tout l&#39;&lt;a href=&#34;http://www.marseille-sympa.com/merou.jpg&#34;&gt;ecosystème J2EE plus généralement&lt;/a&gt;.&lt;/p&gt;</description>
+ <pubDate>Sun, 01 Apr 2012 00:00:00 +0000</pubDate>
+ <guid>https://nicolas.perriault.net/carnet/2012/nouvelles-aventures/</guid>
+ </item>
+ <item>
<title>Nouveau site</title>
<link>https://nicolas.perriault.net/carnet/2012/nouveau-site/</link>
<description>&lt;p&gt;&lt;strong&gt;J&#39;avais envie de fédérer l&#39;ensemble de ma &lt;em&gt;production numérique&lt;/em&gt; au sein d&#39;un seul et même site, c&#39;est donc chose faite si vous lisez ces quelques lignes.&lt;/strong&gt;&lt;/p&gt;
View
12 build/carnet/index.html
@@ -7,7 +7,7 @@
<title>Carnet | Nicolas Perriault</title>
<meta name="description" content="Nicolas Perriault's homepage.">
<meta name="viewport" content="width=device-width">
- <link rel="stylesheet" type="text/css" href="/static/packed.css?1331882038">
+ <link rel="stylesheet" type="text/css" href="/static/packed.css?1333283939">
<link rel="alternate" type="application/rss+xml" href="/code/feed/" title="Code (RSS)">
<link rel="alternate" type="application/rss+xml" href="/photography/feed/" title="Photography (RSS)">
<link rel="alternate" type="application/rss+xml" href="/talks/feed/" title="Talks (RSS)">
@@ -38,6 +38,14 @@
<ul class="item-list" itemprop="blogPosts">
<li>
<h3>
+ <a itemprop="url" href="/carnet/2012/nouvelles-aventures/"><span itemprop="name">Nouvelles aventures</span></a>
+ | <time datetime="2012-04-01">2012-04-01</time>
+ </h3>
+ <p><q itemprop="description"><em>Cela fait quelques mois que je m&#39;interroge sur la pérennité de mon activité en temps qu&#39;indépendant, car force est de constater que la ...</em></q></p>
+ <hr>
+ </li>
+ <li>
+ <h3>
<a itemprop="url" href="/carnet/2012/nouveau-site/"><span itemprop="name">Nouveau site</span></a>
| <time datetime="2012-03-03">2012-03-03</time>
</h3>
@@ -106,7 +114,7 @@
<!-- /container -->
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js"></script>
<script>window.jQuery || document.write('<script src="js/libs/jquery-1.7.1.min.js"><\/script>')</script>
- <script type="text/javascript" src="/static/packed.js?1331882039"></script>
+ <script type="text/javascript" src="/static/packed.js?1333283940"></script>
<script src="//platform.twitter.com/widgets.js" charset="utf-8"></script>
</body>
</html>
View
102 build/code/2010/about-rest-frameworks/index.html
@@ -7,7 +7,7 @@
<title>About RESTful features of modern Web frameworks | Code | Nicolas Perriault</title>
<meta name="description" content="Nicolas Perriault's homepage.">
<meta name="viewport" content="width=device-width">
- <link rel="stylesheet" type="text/css" href="/static/packed.css?1331882038">
+ <link rel="stylesheet" type="text/css" href="/static/packed.css?1333283939">
<link rel="alternate" type="application/rss+xml" href="/code/feed/" title="Code (RSS)">
<link rel="alternate" type="application/rss+xml" href="/photography/feed/" title="Photography (RSS)">
<link rel="alternate" type="application/rss+xml" href="/talks/feed/" title="Talks (RSS)">
@@ -38,65 +38,57 @@
<p>Frameworks like <a href="http://www.symfony-project.org/">Symfony</a> or <a href="http://rubyonrails.org/">rails</a> (and probably many others) provide a very convenient feature named <em>RESTful</em> routing, aka HTTP-aware urls and controllers, generally associated with an object/url mapping mechanism to expose Model entites and several available actions on them over HTTP.</p>
<p>This is really useful, especially when you deal with WebServices on a daily basis, or if you want to reuse your controllers in both <em>standard html</em> or <em>service oriented architecture</em> (SOA) contexts.</p>
<p>For example, with Symfony, you can declare an HTTP routes collection this way (all examples are taken from the <a href="http://github.com/n1k0/sftunes">Sftunes Symfony application</a> I recently released on <em>github</em>):</p>
-<div class="codehilite"><pre><span class="c"># routing.yml</span>
-<span class="n">fortune</span><span class="p">:</span>
- <span class="nb">class</span><span class="p">:</span> <span class="n">sfDoctrineRouteCollection</span>
- <span class="n">options</span><span class="p">:</span>
- <span class="n">model</span><span class="p">:</span> <span class="n">Fortune</span>
- <span class="n">action</span><span class="p">:</span> <span class="p">[</span><span class="n">list</span><span class="p">,</span> <span class="n">new</span><span class="p">,</span> <span class="n">create</span><span class="p">,</span> <span class="n">edit</span><span class="p">,</span> <span class="n">show</span><span class="p">]</span>
- <span class="n">object_actions</span><span class="p">:</span>
- <span class="n">comment</span><span class="p">:</span> <span class="n">post</span>
- <span class="n">down</span><span class="p">:</span> <span class="n">put</span>
- <span class="n">up</span><span class="p">:</span> <span class="n">put</span>
- <span class="n">collection_actions</span><span class="p">:</span>
- <span class="n">top</span><span class="p">:</span> <span class="k">get</span>
- <span class="n">worst</span><span class="p">:</span> <span class="k">get</span>
-</pre></div>
-
-
+<pre><code># routing.yml
+fortune:
+ class: sfDoctrineRouteCollection
+ options:
+ model: Fortune
+ action: [list, new, create, edit, show]
+ object_actions:
+ comment: post
+ down: put
+ up: put
+ collection_actions:
+ top: get
+ worst: get
+</code></pre>
<p>Here the <code>fortune</code> route collection will expose the <code>Fortune</code> Doctrine ORM model over HTTP, using available HTTP verbs like <code>GET</code>, <code>PUT</code>, <code>POST</code> or <code>DELETE</code> for example, hence providing basic CRUD operations (see <a href="http://www.symfony-project.org/reference/1_4/en/10-Routing#chapter_10_sfroutecollection">documentation</a>).</p>
<p>You will then be able to obtain several Symfony routes, to list them just run the <code>app:routes</code> task from the command line:</p>
-<div class="codehilite"><pre><span class="o">~</span> $ <span class="o">./</span><span class="n">symfony</span> <span class="n">app</span><span class="p">:</span><span class="n">routes</span> <span class="n">main</span>
-<span class="o">&gt;&gt;</span> <span class="n">app</span> <span class="n">Current</span> <span class="n">routes</span> <span class="k">for</span> <span class="n">application</span> &quot;<span class="n">main</span>&quot;
-<span class="n">Name</span> <span class="n">Method</span> <span class="n">Pattern</span>
-<span class="n">fortune_top</span> <span class="n">GET</span> <span class="o">/</span><span class="n">fortune</span><span class="o">/</span><span class="n">top</span><span class="p">.:</span><span class="n">sf_format</span>
-<span class="n">fortune_worst</span> <span class="n">GET</span> <span class="o">/</span><span class="n">fortune</span><span class="o">/</span><span class="n">worst</span><span class="p">.:</span><span class="n">sf_format</span>
-<span class="n">fortune</span> <span class="n">GET</span> <span class="o">/</span><span class="n">fortune</span><span class="p">.:</span><span class="n">sf_format</span>
-<span class="n">fortune_new</span> <span class="n">GET</span> <span class="o">/</span><span class="n">fortune</span><span class="o">/</span><span class="n">new</span><span class="p">.:</span><span class="n">sf_format</span>
-<span class="n">fortune_create</span> <span class="n">POST</span> <span class="o">/</span><span class="n">fortune</span><span class="p">.:</span><span class="n">sf_format</span>
-<span class="n">fortune_edit</span> <span class="n">GET</span> <span class="o">/</span><span class="n">fortune</span><span class="o">/</span><span class="p">:</span><span class="n">id</span><span class="o">/</span><span class="n">edit</span><span class="p">.:</span><span class="n">sf_format</span>
-<span class="n">fortune_update</span> <span class="n">PUT</span> <span class="o">/</span><span class="n">fortune</span><span class="o">/</span><span class="p">:</span><span class="n">id</span><span class="p">.:</span><span class="n">sf_format</span>
-<span class="n">fortune_delete</span> <span class="n">DELETE</span> <span class="o">/</span><span class="n">fortune</span><span class="o">/</span><span class="p">:</span><span class="n">id</span><span class="p">.:</span><span class="n">sf_format</span>
-<span class="n">fortune_show</span> <span class="n">GET</span> <span class="o">/</span><span class="n">fortune</span><span class="o">/</span><span class="p">:</span><span class="n">id</span><span class="p">.:</span><span class="n">sf_format</span>
-<span class="n">fortune_comment</span> <span class="n">POST</span> <span class="o">/</span><span class="n">fortune</span><span class="o">/</span><span class="p">:</span><span class="n">id</span><span class="o">/</span><span class="n">comment</span><span class="p">.:</span><span class="n">sf_format</span>
-<span class="n">fortune_down</span> <span class="n">PUT</span> <span class="o">/</span><span class="n">fortune</span><span class="o">/</span><span class="p">:</span><span class="n">id</span><span class="o">/</span><span class="n">down</span><span class="p">.:</span><span class="n">sf_format</span>
-<span class="n">fortune_up</span> <span class="n">PUT</span> <span class="o">/</span><span class="n">fortune</span><span class="o">/</span><span class="p">:</span><span class="n">id</span><span class="o">/</span><span class="n">up</span><span class="p">.:</span><span class="n">sf_format</span>
-<span class="n">homepage</span> <span class="n">ANY</span> <span class="o">/</span>
-</pre></div>
-
-
+<pre><code>~ $ ./symfony app:routes main
+&gt;&gt; app Current routes for application "main"
+Name Method Pattern
+fortune_top GET /fortune/top.:sf_format
+fortune_worst GET /fortune/worst.:sf_format
+fortune GET /fortune.:sf_format
+fortune_new GET /fortune/new.:sf_format
+fortune_create POST /fortune.:sf_format
+fortune_edit GET /fortune/:id/edit.:sf_format
+fortune_update PUT /fortune/:id.:sf_format
+fortune_delete DELETE /fortune/:id.:sf_format
+fortune_show GET /fortune/:id.:sf_format
+fortune_comment POST /fortune/:id/comment.:sf_format
+fortune_down PUT /fortune/:id/down.:sf_format
+fortune_up PUT /fortune/:id/up.:sf_format
+homepage ANY /
+</code></pre>
<p>By calling an url such as <code>/fortune/2.html</code> using the <code>GET</code> verb, you'll obtain a response in <em>text/html</em> format, and Symfony will use a standard HTML template to decorate it -- whereas if you call <code>/fortune/2.json</code> using the <code>DELETE</code> verb, you'll ask for the deletion of the fortune related instance and receive a response in JSON format (at least if you provided the related JSON decoration template, of course).</p>
<p>That's pretty fancy, but a common mistake is to generate links from templates calling verbs other than <code>GET</code>, for example here the <code>fortune_up</code> and <code>fortune_down</code> routes aim to be called via <code>PUT</code> (because they imply a modification of a <code>Fortune</code> object instance), and you may be tempted to write something like this in you templates:</p>
-<div class="codehilite"><pre><span class="cp">&lt;?php</span> <span class="k">echo</span> <span class="nx">link_to</span><span class="p">(</span><span class="s1">&#39;Vote down this fortune&#39;</span><span class="p">,</span> <span class="s1">&#39;fortune_down&#39;</span><span class="p">,</span> <span class="nv">$fortune</span><span class="p">,</span> <span class="k">array</span><span class="p">(</span>
- <span class="s1">&#39;method&#39;</span> <span class="o">=&gt;</span> <span class="s1">&#39;put&#39;</span><span class="p">,</span>
-<span class="p">))</span> <span class="cp">?&gt;</span>
-</pre></div>
-
-
+<pre><code>&lt;?php echo link_to('Vote down this fortune', 'fortune_down', $fortune, array(
+ 'method' =&gt; 'put',
+)) ?&gt;
+</code></pre>
<p>While this is perfectly possible technically speaking, a quick look at the rendered HTML code will temper the interest of this approach:</p>
-<div class="codehilite"><pre><span class="nt">&lt;a</span> <span class="na">onclick=</span><span class="s">&quot;var f = document.createElement(&#39;form&#39;); f.style.display = &#39;none&#39;;</span>
-<span class="s"> this.parentNode.appendChild(f); f.method = &#39;post&#39;; f.action = this.href;</span>
-<span class="s"> var m = document.createElement(&#39;input&#39;); m.setAttribute(&#39;type&#39;, &#39;hidden&#39;);</span>
-<span class="s"> m.setAttribute(&#39;name&#39;, &#39;sf_method&#39;); m.setAttribute(&#39;value&#39;, &#39;put&#39;);</span>
-<span class="s"> f.appendChild(m);var m=document.createElement(&#39;input&#39;);m.setAttribute(&#39;type&#39;, &#39;hidden&#39;);</span>
-<span class="s"> m.setAttribute(&#39;name&#39;, &#39;_csrf_token&#39;);</span>
-<span class="s"> m.setAttribute(&#39;value&#39;, &#39;d26d99f7f4f97lsdhklqejshdjkshdf860124&#39;);</span>
-<span class="s"> f.appendChild(m);f.submit();return false;&quot;</span> <span class="na">href=</span><span class="s">&quot;/main_dev.php/fortune/19/down&quot;</span><span class="nt">&gt;</span>
+<pre><code>&lt;a onclick="var f = document.createElement('form'); f.style.display = 'none';
+ this.parentNode.appendChild(f); f.method = 'post'; f.action = this.href;
+ var m = document.createElement('input'); m.setAttribute('type', 'hidden');
+ m.setAttribute('name', 'sf_method'); m.setAttribute('value', 'put');
+ f.appendChild(m);var m=document.createElement('input');m.setAttribute('type', 'hidden');
+ m.setAttribute('name', '_csrf_token');
+ m.setAttribute('value', 'd26d99f7f4f97lsdhklqejshdjkshdf860124');
+ f.appendChild(m);f.submit();return false;" href="/main_dev.php/fortune/19/down"&gt;
Vote down this fortune
-<span class="nt">&lt;/a&gt;</span>
-</pre></div>
-
-
+&lt;/a&gt;
+</code></pre>
<p>Yes, calling <code>link_to()</code> with the <code>method</code> option set to something else than <code>GET</code> will generate a form to challenge the url with the correct HTTP verb (through the kinda magic <code>sf_method</code> request parameter), dynamically using Javascript. Not really clean, unobstrusive and accessible. <strong>A link should always only handle <code>GET</code> verb, because it's just a link to another resource in <em>view mode</em>, not a modification of it.</strong> So you should rather use a <code>&lt;form/&gt;</code> tag to deal with such kind of operations in your code, always.</p>
<p>But there's more: imagine you want to deal with a <code>Fortune</code> modification form, still by using the <code>PUT</code> http verb and the <code>fortune_update</code> route, in a <em>standard html</em> context (not a WebService one); you have a form so it's okay? It's not, a browser, even the most modern one in 2010, will not understand something else than <code>GET</code> and <code>POST</code>. That's a shame actually. Symfony circumvents the problem by adding a supplementary <code>sf_method</code> hidden parameter to the form fields, so the targetted controller will be able to detect an incoming <code>PUT</code> request, but <strong>this is clearly a kind of patch applied to HTTP support in Browsers</strong>.</p>
<p>I'm searching for a conclusion, but can't find one except <strong>why on Earth modern browsers don't deal with something else than <code>GET</code> and <code>POST</code> nowadays?</strong></p>
@@ -148,7 +140,7 @@
<!-- /container -->
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js"></script>
<script>window.jQuery || document.write('<script src="js/libs/jquery-1.7.1.min.js"><\/script>')</script>
- <script type="text/javascript" src="/static/packed.js?1331882039"></script>
+ <script type="text/javascript" src="/static/packed.js?1333283940"></script>
<script src="//platform.twitter.com/widgets.js" charset="utf-8"></script>
</body>
</html>
View
110 build/code/2010/custom-deployment-tasks/index.html
@@ -7,7 +7,7 @@
<title>Tâches de déploiement spécifiques avec Symfony | Code | Nicolas Perriault</title>
<meta name="description" content="Nicolas Perriault's homepage.">
<meta name="viewport" content="width=device-width">
- <link rel="stylesheet" type="text/css" href="/static/packed.css?1331882038">
+ <link rel="stylesheet" type="text/css" href="/static/packed.css?1333283939">
<link rel="alternate" type="application/rss+xml" href="/code/feed/" title="Code (RSS)">
<link rel="alternate" type="application/rss+xml" href="/photography/feed/" title="Photography (RSS)">
<link rel="alternate" type="application/rss+xml" href="/talks/feed/" title="Talks (RSS)">
@@ -36,71 +36,65 @@
<section>
<p><a href="http://www.symfony-project.org/">Symfony</a> propose une tâche de déploiement distant utilisant <a href="http://fr.wikipedia.org/wiki/Rsync"><code>rsync</code></a> fort pratique&nbsp;: une fois configurés les <a href="http://www.symfony-project.org/jobeet/1_4/Doctrine/en/22#chapter_22_deploying">paramètres du serveur distant</a> dans le fichier <code>config/properties.ini</code> de votre projet, un simple appel en ligne de commande synchronisera les fichiers du projet présents sur votre système de fichiers local vers l'hôte distant. Et si vous utilisez une <a href="http://prendreuncafe.com/blog/post/2005/08/29/262-installer-sa-cle-ssh-sur-un-serveur-distant">clé SSH</a>, l'opération ne vous demandera même pas de saisir votre mot de passe&nbsp;!</p>
-<div class="codehilite"><pre>$ <span class="o">./</span><span class="n">symfony</span> <span class="n">project</span><span class="p">:</span><span class="n">deploy</span> <span class="n">monserveur</span> <span class="o">--</span><span class="n">go</span>
-</pre></div>
-
-
+<pre><code>$ ./symfony project:deploy monserveur --go
+</code></pre>
<p>Mais bien souvent, nous avons besoin de plus&nbsp;: préparer un certain nombre de fichiers statiques comme les assets CSS, JavaScript ou les images, ou vider le cache sur la ou les machines distantes pour prendre en compte d'éventuelles modifications de la configuration ou du templating sur la plateforme de production (qui exploite l'environnement du même nom, nous sommes bien d'accord).</p>
<p>Aussi, il est très simple de faire face à ces besoins spécifiques en créant vous même une tâche de déploiement projet, en surclassant la classe <code>sfProjectDeployTask</code> fournie en standard par Symfony. Par exemple, voici la tâche de déploiement que j'utilise pour la mise à jour du site <a href="http://www.akei.com/">Akei</a>, exploitant mon plugin <a href="http://github.com/n1k0/npAssetsOptimizerPlugin"><code>npAssetsOptimizerPlugin</code></a> pour la gestion de la minification et l'assemblage des fichiers JavaScript, CSS et images PNG &nbsp;:</p>
-<div class="codehilite"><pre><span class="cp">&lt;?php</span>
-<span class="k">class</span> <span class="nc">AkeiDeployTask</span> <span class="k">extends</span> <span class="nx">sfProjectDeployTask</span>
-<span class="p">{</span>
- <span class="sd">/**</span>
-<span class="sd"> * @see sfProjectDeployTask</span>
-<span class="sd"> */</span>
- <span class="k">protected</span> <span class="k">function</span> <span class="nf">configure</span><span class="p">()</span>
- <span class="p">{</span>
- <span class="nv">$this</span><span class="o">-&gt;</span><span class="na">addArguments</span><span class="p">(</span><span class="k">array</span><span class="p">(</span>
- <span class="k">new</span> <span class="nx">sfCommandArgument</span><span class="p">(</span><span class="s1">&#39;server&#39;</span><span class="p">,</span> <span class="nx">sfCommandArgument</span><span class="o">::</span><span class="na">REQUIRED</span><span class="p">,</span> <span class="s1">&#39;The server name&#39;</span><span class="p">),</span>
- <span class="p">));</span>
-
- <span class="nv">$this</span><span class="o">-&gt;</span><span class="na">addOptions</span><span class="p">(</span><span class="k">array</span><span class="p">(</span>
- <span class="k">new</span> <span class="nx">sfCommandOption</span><span class="p">(</span><span class="s1">&#39;go&#39;</span><span class="p">,</span> <span class="k">null</span><span class="p">,</span> <span class="nx">sfCommandOption</span><span class="o">::</span><span class="na">PARAMETER_NONE</span><span class="p">,</span> <span class="s1">&#39;Do the deployment&#39;</span><span class="p">),</span>
- <span class="k">new</span> <span class="nx">sfCommandOption</span><span class="p">(</span><span class="s1">&#39;rsync-dir&#39;</span><span class="p">,</span> <span class="k">null</span><span class="p">,</span> <span class="nx">sfCommandOption</span><span class="o">::</span><span class="na">PARAMETER_REQUIRED</span><span class="p">,</span> <span class="s1">&#39;The directory where to look for rsync*.txt files&#39;</span><span class="p">,</span> <span class="s1">&#39;config&#39;</span><span class="p">),</span>
- <span class="k">new</span> <span class="nx">sfCommandOption</span><span class="p">(</span><span class="s1">&#39;rsync-options&#39;</span><span class="p">,</span> <span class="k">null</span><span class="p">,</span> <span class="nx">sfCommandOption</span><span class="o">::</span><span class="na">PARAMETER_OPTIONAL</span><span class="p">,</span> <span class="s1">&#39;To options to pass to the rsync executable&#39;</span><span class="p">,</span> <span class="s1">&#39;-azC --force --delete --progress&#39;</span><span class="p">),</span>
- <span class="k">new</span> <span class="nx">sfCommandOption</span><span class="p">(</span><span class="s1">&#39;optimize&#39;</span><span class="p">,</span> <span class="k">null</span><span class="p">,</span> <span class="nx">sfCommandOption</span><span class="o">::</span><span class="na">PARAMETER_OPTIONAL</span><span class="p">,</span> <span class="s1">&#39;The asset optimizations to make before deploying&#39;</span><span class="p">),</span>
- <span class="p">));</span>
+<pre><code>&lt;?php
+class AkeiDeployTask extends sfProjectDeployTask
+{
+ /**
+ * @see sfProjectDeployTask
+ */
+ protected function configure()
+ {
+ $this-&gt;addArguments(array(
+ new sfCommandArgument('server', sfCommandArgument::REQUIRED, 'The server name'),
+ ));
- <span class="nv">$this</span><span class="o">-&gt;</span><span class="na">namespace</span> <span class="o">=</span> <span class="s1">&#39;akei&#39;</span><span class="p">;</span>
- <span class="nv">$this</span><span class="o">-&gt;</span><span class="na">name</span> <span class="o">=</span> <span class="s1">&#39;deploy&#39;</span><span class="p">;</span>
- <span class="nv">$this</span><span class="o">-&gt;</span><span class="na">briefDescription</span> <span class="o">=</span> <span class="s1">&#39;Deploys Akei website to a given server&#39;</span><span class="p">;</span>
- <span class="p">}</span>
+ $this-&gt;addOptions(array(
+ new sfCommandOption('go', null, sfCommandOption::PARAMETER_NONE, 'Do the deployment'),
+ new sfCommandOption('rsync-dir', null, sfCommandOption::PARAMETER_REQUIRED, 'The directory where to look for rsync*.txt files', 'config'),
+ new sfCommandOption('rsync-options', null, sfCommandOption::PARAMETER_OPTIONAL, 'To options to pass to the rsync executable', '-azC --force --delete --progress'),
+ new sfCommandOption('optimize', null, sfCommandOption::PARAMETER_OPTIONAL, 'The asset optimizations to make before deploying'),
+ ));
- <span class="sd">/**</span>
-<span class="sd"> * @see sfProjectDeployTask</span>
-<span class="sd"> */</span>
- <span class="k">protected</span> <span class="k">function</span> <span class="nf">execute</span><span class="p">(</span><span class="nv">$arguments</span> <span class="o">=</span> <span class="k">array</span><span class="p">(),</span> <span class="nv">$options</span> <span class="o">=</span> <span class="k">array</span><span class="p">())</span>
- <span class="p">{</span>
- <span class="c1">// Assets</span>
- <span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="nb">is_null</span><span class="p">(</span><span class="nv">$options</span><span class="p">[</span><span class="s1">&#39;optimize&#39;</span><span class="p">]))</span>
- <span class="p">{</span>
- <span class="nv">$this</span><span class="o">-&gt;</span><span class="na">logSection</span><span class="p">(</span><span class="s1">&#39;deploy&#39;</span><span class="p">,</span> <span class="s1">&#39;assets optimization before deploying&#39;</span><span class="p">);</span>
- <span class="nv">$task</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">npOptimizeAssetsTask</span><span class="p">(</span><span class="nv">$this</span><span class="o">-&gt;</span><span class="na">dispatcher</span><span class="p">,</span> <span class="nv">$this</span><span class="o">-&gt;</span><span class="na">formatter</span><span class="p">);</span>
- <span class="nv">$task</span><span class="o">-&gt;</span><span class="na">run</span><span class="p">(</span><span class="k">array</span><span class="p">(</span><span class="s1">&#39;application&#39;</span> <span class="o">=&gt;</span> <span class="s1">&#39;main&#39;</span><span class="p">),</span> <span class="k">array</span><span class="p">(</span><span class="s1">&#39;type&#39;</span> <span class="o">=&gt;</span> <span class="nv">$options</span><span class="p">[</span><span class="s1">&#39;optimize&#39;</span><span class="p">]));</span>
- <span class="p">}</span>
+ $this-&gt;namespace = 'akei';
+ $this-&gt;name = 'deploy';
+ $this-&gt;briefDescription = 'Deploys Akei website to a given server';
+ }
- <span class="c1">// Deployment</span>
- <span class="nv">$this</span><span class="o">-&gt;</span><span class="na">logSection</span><span class="p">(</span><span class="s1">&#39;deploy&#39;</span><span class="p">,</span> <span class="s1">&#39;deploying...&#39;</span><span class="p">);</span>
- <span class="k">parent</span><span class="o">::</span><span class="na">execute</span><span class="p">(</span><span class="nv">$arguments</span><span class="p">,</span> <span class="nv">$options</span><span class="p">);</span>
+ /**
+ * @see sfProjectDeployTask
+ */
+ protected function execute($arguments = array(), $options = array())
+ {
+ // Assets
+ if (!is_null($options['optimize']))
+ {
+ $this-&gt;logSection('deploy', 'assets optimization before deploying');
+ $task = new npOptimizeAssetsTask($this-&gt;dispatcher, $this-&gt;formatter);
+ $task-&gt;run(array('application' =&gt; 'main'), array('type' =&gt; $options['optimize']));
+ }
- <span class="c1">// Remote symfony cc</span>
- <span class="k">if</span> <span class="p">(</span><span class="nv">$options</span><span class="p">[</span><span class="s1">&#39;go&#39;</span><span class="p">])</span>
- <span class="p">{</span>
- <span class="nv">$this</span><span class="o">-&gt;</span><span class="na">logSection</span><span class="p">(</span><span class="s1">&#39;deploy&#39;</span><span class="p">,</span> <span class="s1">&#39;remote cache clear&#39;</span><span class="p">);</span>
- <span class="nv">$this</span><span class="o">-&gt;</span><span class="na">getFilesystem</span><span class="p">()</span><span class="o">-&gt;</span><span class="na">execute</span><span class="p">(</span><span class="s1">&#39;ssh user@monserveur.foo &quot;/path/to/www/akei/symfony cache:clear&quot;&#39;</span><span class="p">);</span>
- <span class="p">}</span>
-
- <span class="nv">$this</span><span class="o">-&gt;</span><span class="na">logSection</span><span class="p">(</span><span class="s1">&#39;deploy&#39;</span><span class="p">,</span> <span class="s1">&#39;done.&#39;</span><span class="p">);</span>
- <span class="p">}</span>
-<span class="p">}</span>
-</pre></div>
+ // Deployment
+ $this-&gt;logSection('deploy', 'deploying...');
+ parent::execute($arguments, $options);
+ // Remote symfony cc
+ if ($options['go'])
+ {
+ $this-&gt;logSection('deploy', 'remote cache clear');
+ $this-&gt;getFilesystem()-&gt;execute('ssh user@monserveur.foo "/path/to/www/akei/symfony cache:clear"');
+ }
+ $this-&gt;logSection('deploy', 'done.');
+ }
+}
+</code></pre>
<p>Comme vous pouvez le constater, cette tâche déclare un espace de nom <code>akei</code> et propose une option supplémentaire, <code>optimize</code>, permettant de préparer les assets avant déploiement&nbsp;:</p>
-<div class="codehilite"><pre>$ <span class="o">./</span><span class="n">symfony</span> <span class="n">akei</span><span class="p">:</span><span class="n">deploy</span> <span class="n">monserveur</span> <span class="o">--</span><span class="n">optimize</span><span class="p">=</span><span class="n">stylesheet</span> <span class="o">--</span><span class="n">go</span>
-</pre></div>
-
-
+<pre><code>$ ./symfony akei:deploy monserveur --optimize=stylesheet --go
+</code></pre>
<p>Cette commande va tout simplement minifier et assembler les feuilles de style définies par la configuration du plugin <code>npAssetsOptimizerPlugin</code>, déployer les fichiers en production sur la machine <code>monserveur</code> et vider le cache sur la machine distante une fois l'opération effectuée.</p>
<p>Notez d'ailleurs l'emploi du très pratique appel à <code>$this-&gt;getFilesystem()-&gt;execute()</code>, qui permet d'executer des appels à la ligne de commande locale depuis la classe de tâche elle-même&nbsp;; ici, une execution distante à travers SSH.</p>
<p>Bien entendu, cet exemple est très spécifique aux besoins du site Akei, mais vous pourriez en quelques minutes gérer plus finement une tâche de déploiement plus générique et configurable. Pensez-y pour vos projets ;)</p>
@@ -150,7 +144,7 @@
<!-- /container -->
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js"></script>
<script>window.jQuery || document.write('<script src="js/libs/jquery-1.7.1.min.js"><\/script>')</script>
- <script type="text/javascript" src="/static/packed.js?1331882039"></script>
+ <script type="text/javascript" src="/static/packed.js?1333283940"></script>
<script src="//platform.twitter.com/widgets.js" charset="utf-8"></script>
</body>
</html>
View
184 build/code/2010/django-with-pip-virtualenv/index.html
@@ -7,7 +7,7 @@
<title>Installer Django dans un environnement Python virtuel avec pip, virtualenv et virtualenvwrapper | Code | Nicolas Perriault</title>
<meta name="description" content="Nicolas Perriault's homepage.">
<meta name="viewport" content="width=device-width">
- <link rel="stylesheet" type="text/css" href="/static/packed.css?1331882038">
+ <link rel="stylesheet" type="text/css" href="/static/packed.css?1333283939">
<link rel="alternate" type="application/rss+xml" href="/code/feed/" title="Code (RSS)">
<link rel="alternate" type="application/rss+xml" href="/photography/feed/" title="Photography (RSS)">
<link rel="alternate" type="application/rss+xml" href="/talks/feed/" title="Talks (RSS)">
@@ -47,61 +47,45 @@
<h3><code>pip</code>, un installeur de paquet simple et efficace</h3>
<p>D'aucuns de ceux qui utilisent une distribution Linux connaissent le bonheur d'utiliser un gestionnaire de paquets. L'installation de programmes et de librairies s'effectuent la plupart du temps en ligne de commande, et la résolution des dépendances est totalement prise en charge de façon transparente.</p>
<p><a href="http://pypi.python.org/pypi/pip">pip</a> est un gestionnaire de paquets Python, écrit lui-même en Python, qui tient ce rôle à merveille. L'installation de <code>pip</code> est fort simple, pour peu de disposer de <a href="http://pypi.python.org/pypi/setuptools">setup_tools</a>&nbsp;:</p>
-<div class="codehilite"><pre>$ <span class="n">sudo</span> <span class="n">easy_install</span> <span class="n">pip</span>
-</pre></div>
-
-
+<pre><code>$ sudo easy_install pip
+</code></pre>
<p>Pour installer un paquet, par exemple la dernière version stable de Django (la 1.1.1), il vous suffit de taper en ligne de commande&nbsp;:</p>
-<div class="codehilite"><pre>$ <span class="n">sudo</span> <span class="n">pip</span> <span class="n">install</span> <span class="n">Django</span>
-</pre></div>
-
-
+<pre><code>$ sudo pip install Django
+</code></pre>
<p>Pour chercher un paquet, c'est aussi simple que&nbsp;:</p>
-<div class="codehilite"><pre>$ <span class="n">pip</span> <span class="n">search</span> <span class="n">django</span><span class="o">-</span><span class="n">debug</span><span class="o">-</span><span class="n">toolbar</span>
-</pre></div>
-
-
+<pre><code>$ pip search django-debug-toolbar
+</code></pre>
<h3><code>virtualenv</code>, un environnement Python virtuel étanche et cloisonné</h3>
<p><a href="http://pypi.python.org/pypi/virtualenv">virtualenv</a> vous propose ni plus ni moins de créer à la demande des environnements de travail virtuels pour tout ce qui touche à Python&nbsp;: chaque environnement possède ses propres paquets et librairies, voire dispose de sa propre version de l'interpréteur !</p>
<p><a href="http://www.doughellmann.com/projects/virtualenvwrapper/">virtualenvwrapper</a>, quand à lui, est un jeu de scripts utilitaires permettant de créer, modifier, supprimer et - d'une façon plus générale - de travailler efficacement avec <code>virtualenv</code>.</p>
<p>L'installation de <code>virtualenv</code> et de <code>virtualenvwrapper</code>, ça tombe bien, peuvent se faire directement via <code>pip</code>&nbsp;:</p>
-<div class="codehilite"><pre>$ <span class="n">sudo</span> <span class="n">pip</span> <span class="n">install</span> <span class="n">virtualenv</span> <span class="n">virtualenvwrapper</span>
-</pre></div>
-
-
+<pre><code>$ sudo pip install virtualenv virtualenvwrapper
+</code></pre>
<p>Pour finir de configurer l'installation de <code>virtualenv</code>, il nous reste cependant quelques étapes supplémentaires.</p>
<p>Tout d'abord, il nous faut créer le répertoire qui contiendra nos environnements virtuels sur notre machine [^envpath]&nbsp;:</p>
-<div class="codehilite"><pre>$ <span class="n">mkdir</span> <span class="o">~/</span><span class="p">.</span><span class="n">virtualenvs</span>
-</pre></div>
-
-
+<pre><code>$ mkdir ~/.virtualenvs
+</code></pre>
<p>[^envpath]: Vous pouvez bien entendu créer ce répertoire où bon vous semble sur votre système, à partir du moment où votre utilisateur a les droits de lecture et d'écriture dessus.</p>
<p>Il faut également renseigner ce chemin dans la variable d'environnement <code>$WORKON_HOME</code> et instancier la gestion des environnements virtuels, le plus simple étant alors de placer les déclarations ad-hoc dans le fichier <code>~/.profile</code> de votre compte utilisateur [^prf]&nbsp;:</p>
-<div class="codehilite"><pre>$ <span class="n">echo</span> &quot;<span class="n">export</span> <span class="n">WORKON_HOME</span><span class="p">=</span>$<span class="n">HOME</span><span class="o">/</span><span class="p">.</span><span class="n">virtualenvs</span>&quot; <span class="o">&gt;&gt;</span> <span class="o">~/</span><span class="p">.</span><span class="n">profile</span>
-$ <span class="n">echo</span> &quot;<span class="n">export</span> <span class="n">PIP_VIRTUALENV_BASE</span><span class="p">=</span>$<span class="n">WORKON_HOME</span>&quot; <span class="o">&gt;&gt;</span> <span class="o">~/</span><span class="p">.</span><span class="n">profile</span>
-$ <span class="n">echo</span> &quot;<span class="n">export</span> <span class="n">PIP_RESPECT_VIRTUALENV</span><span class="p">=</span><span class="n">true</span>&quot; <span class="o">&gt;&gt;</span> <span class="o">~/</span><span class="p">.</span><span class="n">profile</span>
-$ <span class="n">echo</span> &quot;<span class="n">source</span> <span class="o">/</span><span class="n">usr</span><span class="o">/</span><span class="n">local</span><span class="o">/</span><span class="n">bin</span><span class="o">/</span><span class="n">virtualenvwrapper</span><span class="p">.</span><span class="n">sh</span>&quot; <span class="o">&gt;&gt;</span> <span class="o">~/</span><span class="p">.</span><span class="n">profile</span>
-</pre></div>
-
-
+<pre><code>$ echo "export WORKON_HOME=$HOME/.virtualenvs" &gt;&gt; ~/.profile
+$ echo "export PIP_VIRTUALENV_BASE=$WORKON_HOME" &gt;&gt; ~/.profile
+$ echo "export PIP_RESPECT_VIRTUALENV=true" &gt;&gt; ~/.profile
+$ echo "source /usr/local/bin/virtualenvwrapper.sh" &gt;&gt; ~/.profile
+</code></pre>
<p>[^prf]: le fichier <code>~/.profile</code> est chargé à chaque démarrage de session Max OS X. Utilisateurs de GNU/Linux, l'équivalent est le fichier <code>~/.bashrc</code>.</p>
<blockquote>
<p><strong>Note&nbsp;:</strong> il se peut que selon le mode d'installation utilisé, le chemin vers le fichier <code>/usr/local/bin/virtualenvwrapper.sh</code> soit à adapter spécifiquement.</p>
</blockquote>
<p>Comme nous venons d'ajouter des directives à notre fichier <code>~/.profile</code>, il faut le recharger&nbsp;:</p>
-<div class="codehilite"><pre>$ <span class="n">source</span> <span class="o">~/</span><span class="p">.</span><span class="n">profile</span>
-</pre></div>
-
-
+<pre><code>$ source ~/.profile
+</code></pre>
<h3>Créer son premier environnement virtuel</h3>
<p>Reprenons le cas de nos deux projets <code>A</code> et <code>B</code> ; nous avons besoin de créer deux environnements virtuels distincts pour travailler sereinement avec les paquets adéquats pour chacun d'eux&nbsp;:</p>
<p>Nous allons nous concentrer sur la création du premier environnement, pour l'occasion destiné à travailler sur le projet <code>A</code>&nbsp;:</p>
-<div class="codehilite"><pre>$ <span class="n">mkvirtualenv</span> <span class="n">DjangoEnvX</span> <span class="o">--</span><span class="n">no</span><span class="o">-</span><span class="n">site</span><span class="o">-</span><span class="n">packages</span>
-<span class="n">New</span> <span class="n">python</span> <span class="n">executable</span> <span class="n">in</span> <span class="n">DjangoEnvX</span><span class="o">/</span><span class="n">bin</span><span class="o">/</span><span class="n">python</span>
-<span class="n">Installing</span> <span class="n">setuptools</span><span class="p">............</span><span class="n">done</span><span class="p">.</span>
-</pre></div>
-
-
+<pre><code>$ mkvirtualenv DjangoEnvX --no-site-packages
+New python executable in DjangoEnvX/bin/python
+Installing setuptools............done.
+</code></pre>
<p>L'environnement a été créé. Notez trois choses importantes&nbsp;:</p>
<ul>
<li>Les <em>setuptools</em> ont été installés dans l'environnement, ainsi que <code>pip</code> même s'il n'en est pas fait mention ; cela nous permettra de disposer de moyens d'installation depuis l'environnement en question&nbsp;;</li>
@@ -109,19 +93,17 @@
<li>Je ne nomme pas l'environnement de travail du nom du «&nbsp;Projet&nbsp;A&nbsp;», dans la mesure où cet environnement pourrait éventuellement être réutilisé pour d'autres projets ayant des besoins et contraintes similaires.</li>
</ul>
<p>Mais examinons de plus près ce que la commande <code>mkvirtualenv</code> a créé pour nous&nbsp;:</p>
-<div class="codehilite"><pre><span class="o">~</span>$ <span class="n">workon</span> <span class="n">DjangoEnvX</span>
-<span class="p">(</span><span class="n">DjangoEnvX</span><span class="p">)</span><span class="o">~</span> $ <span class="n">cdvirtualenv</span>
-<span class="p">(</span><span class="n">DjangoEnvX</span><span class="p">)</span><span class="o">~/</span><span class="p">.</span><span class="n">virtualenvs</span><span class="o">/</span><span class="n">DjangoEnvX</span> $ <span class="n">ls</span> <span class="o">-</span><span class="n">l</span>
-<span class="n">total</span> 8
-<span class="n">drwxr</span><span class="o">-</span><span class="n">xr</span><span class="o">-</span><span class="n">x</span> 6 <span class="n">niko</span> <span class="n">staff</span> 204 <span class="n">May</span> 5 16<span class="p">:</span>08 <span class="p">.</span>
-<span class="n">drwxr</span><span class="o">-</span><span class="n">xr</span><span class="o">-</span><span class="n">x</span> 14 <span class="n">niko</span> <span class="n">staff</span> 476 <span class="n">May</span> 5 16<span class="p">:</span>08 <span class="p">..</span>
-<span class="n">lrwxr</span><span class="o">-</span><span class="n">xr</span><span class="o">-</span><span class="n">x</span> 1 <span class="n">niko</span> <span class="n">staff</span> 63 <span class="n">May</span> 5 16<span class="p">:</span>08 <span class="p">.</span><span class="n">Python</span> <span class="o">-&gt;</span> <span class="o">/</span><span class="n">System</span><span class="o">/</span><span class="n">Library</span><span class="o">/</span><span class="n">Frameworks</span><span class="o">/</span><span class="n">Python</span><span class="p">.</span><span class="n">framework</span><span class="o">/</span><span class="n">Versions</span><span class="o">/</span>2<span class="p">.</span>6<span class="o">/</span><span class="n">Python</span>
-<span class="n">drwxr</span><span class="o">-</span><span class="n">xr</span><span class="o">-</span><span class="n">x</span> 9 <span class="n">niko</span> <span class="n">staff</span> 306 <span class="n">May</span> 5 16<span class="p">:</span>08 <span class="n">bin</span>
-<span class="n">drwxr</span><span class="o">-</span><span class="n">xr</span><span class="o">-</span><span class="n">x</span> 3 <span class="n">niko</span> <span class="n">staff</span> 102 <span class="n">May</span> 5 16<span class="p">:</span>08 <span class="n">include</span>
-<span class="n">drwxr</span><span class="o">-</span><span class="n">xr</span><span class="o">-</span><span class="n">x</span> 3 <span class="n">niko</span> <span class="n">staff</span> 102 <span class="n">May</span> 5 16<span class="p">:</span>08 <span class="n">lib</span>
-</pre></div>
-
-
+<pre><code>~$ workon DjangoEnvX
+(DjangoEnvX)~ $ cdvirtualenv
+(DjangoEnvX)~/.virtualenvs/DjangoEnvX $ ls -l
+total 8
+drwxr-xr-x 6 niko staff 204 May 5 16:08 .
+drwxr-xr-x 14 niko staff 476 May 5 16:08 ..
+lrwxr-xr-x 1 niko staff 63 May 5 16:08 .Python -&gt; /System/Library/Frameworks/Python.framework/Versions/2.6/Python
+drwxr-xr-x 9 niko staff 306 May 5 16:08 bin
+drwxr-xr-x 3 niko staff 102 May 5 16:08 include
+drwxr-xr-x 3 niko staff 102 May 5 16:08 lib
+</code></pre>
<p>Notez les éléments suivants&nbsp;:</p>
<ul>
<li>L'utilisation de la commande <code>workon</code>, fournie par <code>virtualenvwrapper</code>, qui permet d'activer un environnement virtuel de travail ; l'autocomplétion du nom de l'environnement virtuel est d'ailleurs disponible&nbsp;!</li>
@@ -130,68 +112,54 @@
<li>Un préfixe (ici <code>(DjangoEnvX)</code>) est ajouté devant le prompt lorqu'on travaille dans un environnement spécifique&nbsp;: cela permet de toujours savoir dans quel environnement on travaille, afin d'éviter les mauvaises surprises ;)</li>
</ul>
<p>Je peux maintenant installer sereinement les paquets dont j'ai besoin dans le cadre de mon projet <code>A</code>, où que je sois sur le système de fichiers. Par exemple, pour installer la version de dev de Django 1.2 depuis son mirroir git&nbsp;:</p>
-<div class="codehilite"><pre><span class="p">(</span><span class="n">DjangoEnvX</span><span class="p">)</span><span class="o">~</span> $ <span class="n">cd</span> <span class="o">~</span>
-<span class="p">(</span><span class="n">DjangoEnvX</span><span class="p">)</span><span class="o">~</span> $ <span class="n">pip</span> <span class="n">install</span> <span class="o">-</span><span class="n">e</span> <span class="n">git</span><span class="o">+</span><span class="n">http</span><span class="p">:</span><span class="o">//</span><span class="n">github</span><span class="p">.</span><span class="n">com</span><span class="o">/</span><span class="n">django</span><span class="o">/</span><span class="n">django</span><span class="p">.</span><span class="n">git</span>#<span class="n">egg</span><span class="p">=</span><span class="n">django</span>
-</pre></div>
-
-
+<pre><code>(DjangoEnvX)~ $ cd ~
+(DjangoEnvX)~ $ pip install -e git+http://github.com/django/django.git#egg=django
+</code></pre>
<p>Vérifions que la version de développement de Django a bien été installée dans notre environnement <code>DjangoEnvX</code>&nbsp;:</p>
-<div class="codehilite"><pre><span class="p">(</span><span class="n">DjangoEnvX</span><span class="p">)</span><span class="o">~</span> $ <span class="n">cdvirtualenv</span>
-<span class="p">(</span><span class="n">DjangoEnvX</span><span class="p">)</span><span class="o">~/</span><span class="p">.</span><span class="n">virtualenvs</span><span class="o">/</span><span class="n">DjangoEnvX</span> $ <span class="n">ll</span> <span class="n">src</span>
-<span class="n">total</span> 0
-<span class="n">drwxr</span><span class="o">-</span><span class="n">xr</span><span class="o">-</span><span class="n">x</span> 3 <span class="n">niko</span> <span class="n">staff</span> 102 <span class="n">May</span> 5 17<span class="p">:</span>07 <span class="p">.</span>
-<span class="n">drwxr</span><span class="o">-</span><span class="n">xr</span><span class="o">-</span><span class="n">x</span> 7 <span class="n">niko</span> <span class="n">staff</span> 238 <span class="n">May</span> 5 17<span class="p">:</span>08 <span class="p">..</span>
-<span class="n">drwxr</span><span class="o">-</span><span class="n">xr</span><span class="o">-</span><span class="n">x</span> 16 <span class="n">niko</span> <span class="n">staff</span> 544 <span class="n">May</span> 5 17<span class="p">:</span>08 <span class="n">django</span>
-<span class="p">(</span><span class="n">DjangoEnvX</span><span class="p">)</span><span class="o">~/</span><span class="p">.</span><span class="n">virtualenvs</span><span class="o">/</span><span class="n">DjangoEnvX</span> $ <span class="n">echo</span> <span class="o">-</span><span class="n">e</span> &quot;<span class="n">import</span> <span class="n">django</span><span class="o">\</span><span class="n">nprint</span> <span class="n">django</span><span class="p">.</span><span class="n">get_version</span><span class="p">()</span>&quot;<span class="o">|</span><span class="n">python</span>
-1<span class="p">.</span>2 <span class="nb">beta</span> 1
-</pre></div>
-
-
+<pre><code>(DjangoEnvX)~ $ cdvirtualenv
+(DjangoEnvX)~/.virtualenvs/DjangoEnvX $ ll src
+total 0
+drwxr-xr-x 3 niko staff 102 May 5 17:07 .
+drwxr-xr-x 7 niko staff 238 May 5 17:08 ..
+drwxr-xr-x 16 niko staff 544 May 5 17:08 django
+(DjangoEnvX)~/.virtualenvs/DjangoEnvX $ echo -e "import django\nprint django.get_version()"|python
+1.2 beta 1
+</code></pre>
<p>Installons maintenant de la même façon le paquet <code>django-debug-toolbar</code> en version 0.8.3&nbsp;:</p>
-<div class="codehilite"><pre><span class="p">(</span><span class="n">DjangoEnvX</span><span class="p">)</span><span class="o">~</span> $ <span class="n">pip</span> <span class="n">install</span> <span class="o">-</span><span class="n">e</span> <span class="n">git</span><span class="o">+</span><span class="n">git</span><span class="p">:</span><span class="o">//</span><span class="n">github</span><span class="p">.</span><span class="n">com</span><span class="o">/</span><span class="n">robhudson</span><span class="o">/</span><span class="n">django</span><span class="o">-</span><span class="n">debug</span><span class="o">-</span><span class="n">toolbar</span><span class="p">@</span>0<span class="p">.</span>8<span class="p">.</span>3#<span class="n">egg</span><span class="p">=</span><span class="n">django</span><span class="o">-</span><span class="n">debug</span><span class="o">-</span><span class="n">toolbar</span>
-</pre></div>
-
-
+<pre><code>(DjangoEnvX)~ $ pip install -e git+git://github.com/robhudson/django-debug-toolbar@0.8.3#egg=django-debug-toolbar
+</code></pre>
<p>Nous avons maintenant nos paquets installés, créons un nouveau projet Django. On peut créer un répertoire n'importe où sur le système de fichiers, cela n'a aucune importance&nbsp;: les environnements virtuels et les projets ne sont pas directement liés.</p>
-<div class="codehilite"><pre><span class="p">(</span><span class="n">DjangoEnvX</span><span class="p">)</span><span class="o">~</span> $ <span class="n">cd</span> <span class="o">~/</span><span class="n">Sites</span><span class="o">/</span>
-<span class="p">(</span><span class="n">DjangoEnvX</span><span class="p">)</span><span class="o">~/</span><span class="n">Sites</span> $ <span class="n">django</span><span class="o">-</span><span class="n">admin</span><span class="p">.</span><span class="n">py</span> <span class="n">startproject</span> <span class="n">my_django_project</span>
-<span class="p">(</span><span class="n">DjangoEnvX</span><span class="p">)</span><span class="o">~/</span><span class="n">Sites</span> $ <span class="n">cd</span> <span class="n">my_django_project</span><span class="o">/</span>
-<span class="p">(</span><span class="n">DjangoEnvX</span><span class="p">)</span><span class="o">~/</span><span class="n">Sites</span><span class="o">/</span><span class="n">my_django_project</span> $ <span class="n">ll</span>
-<span class="n">total</span> 24
-<span class="n">drwxr</span><span class="o">-</span><span class="n">xr</span><span class="o">-</span><span class="n">x</span> 6 <span class="n">niko</span> <span class="n">staff</span> 204 <span class="n">May</span> 5 17<span class="p">:</span>36 <span class="p">.</span>
-<span class="n">drwxr</span><span class="o">-</span><span class="n">xr</span><span class="o">-</span><span class="n">x</span> 94 <span class="n">niko</span> <span class="n">staff</span> 3196 <span class="n">May</span> 5 17<span class="p">:</span>36 <span class="p">..</span>
-<span class="o">-</span><span class="n">rw</span><span class="o">-</span><span class="n">r</span><span class="o">--</span><span class="n">r</span><span class="o">--</span> 1 <span class="n">niko</span> <span class="n">staff</span> 0 <span class="n">May</span> 5 17<span class="p">:</span>36 <span class="n">__init__</span><span class="p">.</span><span class="n">py</span>
-<span class="o">-</span><span class="n">rwxr</span><span class="o">-</span><span class="n">xr</span><span class="o">-</span><span class="n">x</span> 1 <span class="n">niko</span> <span class="n">staff</span> 546 <span class="n">May</span> 5 17<span class="p">:</span>36 <span class="n">manage</span><span class="p">.</span><span class="n">py</span>
-<span class="o">-</span><span class="n">rw</span><span class="o">-</span><span class="n">r</span><span class="o">--</span><span class="n">r</span><span class="o">--</span> 1 <span class="n">niko</span> <span class="n">staff</span> 3313 <span class="n">May</span> 5 17<span class="p">:</span>36 <span class="n">settings</span><span class="p">.</span><span class="n">py</span>
-<span class="o">-</span><span class="n">rw</span><span class="o">-</span><span class="n">r</span><span class="o">--</span><span class="n">r</span><span class="o">--</span> 1 <span class="n">niko</span> <span class="n">staff</span> 564 <span class="n">May</span> 5 17<span class="p">:</span>36 <span class="n">urls</span><span class="p">.</span><span class="n">py</span>
-<span class="p">(</span><span class="n">DjangoEnvX</span><span class="p">)</span><span class="o">~/</span><span class="n">Sites</span><span class="o">/</span><span class="n">my_django_project</span> $ <span class="o">./</span><span class="n">manage</span><span class="p">.</span><span class="n">py</span> <span class="n">runserver</span>
-<span class="n">Validating</span> <span class="n">models</span><span class="p">...</span>
-0 <span class="n">errors</span> <span class="n">found</span>
-
-<span class="n">Django</span> <span class="n">version</span> 1<span class="p">.</span>2 <span class="nb">beta</span> 1<span class="p">,</span> <span class="n">using</span> <span class="n">settings</span> <span class="s">&#39;my_django_project.settings&#39;</span>
-<span class="n">Development</span> <span class="n">server</span> <span class="n">is</span> <span class="n">running</span> <span class="n">at</span> <span class="n">http</span><span class="p">:</span><span class="o">//</span>127<span class="p">.</span>0<span class="p">.</span>0<span class="p">.</span>1<span class="p">:</span>8000<span class="o">/</span>
-<span class="n">Quit</span> <span class="n">the</span> <span class="n">server</span> <span class="n">with</span> <span class="n">CONTROL</span><span class="o">-</span><span class="n">C</span><span class="p">.</span>
-</pre></div>
-
-
+<pre><code>(DjangoEnvX)~ $ cd ~/Sites/
+(DjangoEnvX)~/Sites $ django-admin.py startproject my_django_project
+(DjangoEnvX)~/Sites $ cd my_django_project/
+(DjangoEnvX)~/Sites/my_django_project $ ll
+total 24
+drwxr-xr-x 6 niko staff 204 May 5 17:36 .
+drwxr-xr-x 94 niko staff 3196 May 5 17:36 ..
+-rw-r--r-- 1 niko staff 0 May 5 17:36 __init__.py
+-rwxr-xr-x 1 niko staff 546 May 5 17:36 manage.py
+-rw-r--r-- 1 niko staff 3313 May 5 17:36 settings.py
+-rw-r--r-- 1 niko staff 564 May 5 17:36 urls.py
+(DjangoEnvX)~/Sites/my_django_project $ ./manage.py runserver
+Validating models...
+0 errors found
+
+Django version 1.2 beta 1, using settings 'my_django_project.settings'
+Development server is running at http://127.0.0.1:8000/
+Quit the server with CONTROL-C.
+</code></pre>
<p>Voila, nous pouvons travailler sur notre projet dans l'environnement <code>DjangoEnvX</code> l'esprit serein. On pourra éventuellement ajouter d'autre paquets, ceux-ci ne seront toujours installés que pour cet environnement. Si d'aventure nous voulions versionner la liste des dépendances installées va <code>pip</code>, c'est aussi simple que&nbsp;:</p>
-<div class="codehilite"><pre><span class="p">(</span><span class="n">DjangoEnvX</span><span class="p">)</span><span class="o">~/</span><span class="n">Sites</span><span class="o">/</span><span class="n">my_django_project</span> $ <span class="n">pip</span> <span class="n">freeze</span> <span class="o">&gt;</span> <span class="n">requirements</span><span class="p">.</span><span class="n">txt</span>
-</pre></div>
-
-
+<pre><code>(DjangoEnvX)~/Sites/my_django_project $ pip freeze &gt; requirements.txt
+</code></pre>
<p>Le fichier <code>requirements.txt</code> ainsi créé contiendra la liste de tous les paquets installés dans l'environnement <code>DjangoEnvX</code>&nbsp;:</p>
-<div class="codehilite"><pre><span class="p">(</span><span class="n">DjangoEnvX</span><span class="p">)</span><span class="o">~/</span><span class="n">Sites</span><span class="o">/</span><span class="n">my_django_project</span> $ <span class="nb">cat</span> <span class="n">requirements</span><span class="p">.</span><span class="n">txt</span>
-<span class="o">-</span><span class="n">e</span> <span class="n">git</span><span class="o">+</span><span class="n">http</span><span class="p">:</span><span class="o">//</span><span class="n">github</span><span class="p">.</span><span class="n">com</span><span class="o">/</span><span class="n">django</span><span class="o">/</span><span class="n">django</span><span class="p">.</span><span class="n">git</span><span class="p">@</span>25<span class="n">a45619fe5d7ff3d4f2dbf8f8879a3a00c3625d</span>#<span class="n">egg</span><span class="p">=</span><span class="n">Django</span><span class="o">-</span>1<span class="p">.</span>2<span class="n">_beta_1</span><span class="o">-</span><span class="n">py2</span><span class="p">.</span>6<span class="o">-</span><span class="n">dev</span>
-<span class="o">-</span><span class="n">e</span> <span class="n">git</span><span class="p">:</span><span class="o">//</span><span class="n">github</span><span class="p">.</span><span class="n">com</span><span class="o">/</span><span class="n">robhudson</span><span class="o">/</span><span class="n">django</span><span class="o">-</span><span class="n">debug</span><span class="o">-</span><span class="n">toolbar</span><span class="p">@</span><span class="n">ee1811238e91ae0ad33413b0d40d2f8482101951</span>#<span class="n">egg</span><span class="p">=</span><span class="n">django_debug_toolbar</span><span class="o">-</span>0<span class="p">.</span>8<span class="p">.</span>3<span class="o">-</span><span class="n">py2</span><span class="p">.</span>6<span class="o">-</span><span class="n">dev</span>
-<span class="n">wsgiref</span><span class="o">==</span>0<span class="p">.</span>1<span class="p">.</span>2
-</pre></div>
-
-
+<pre><code>(DjangoEnvX)~/Sites/my_django_project $ cat requirements.txt
+-e git+http://github.com/django/django.git@25a45619fe5d7ff3d4f2dbf8f8879a3a00c3625d#egg=Django-1.2_beta_1-py2.6-dev
+-e git://github.com/robhudson/django-debug-toolbar@ee1811238e91ae0ad33413b0d40d2f8482101951#egg=django_debug_toolbar-0.8.3-py2.6-dev
+wsgiref==0.1.2
+</code></pre>
<p>Libre à vous alors de versionner ce fichier, ce qui permettra à vos collaborateurs d'instancier un nouvel envronnement de travail et d'installer les dépendances requises d'une simple ligne de commande sur son poste de travail&nbsp;:</p>
-<div class="codehilite"><pre><span class="p">(</span><span class="n">WtfDevEnv</span><span class="p">)</span>$ <span class="n">pip</span> <span class="n">install</span> <span class="o">-</span><span class="n">r</span> <span class="o">/</span><span class="n">path</span><span class="o">/</span><span class="n">to</span><span class="o">/</span><span class="n">requirements</span><span class="p">.</span><span class="n">txt</span>
-</pre></div>
-
-
+<pre><code>(WtfDevEnv)$ pip install -r /path/to/requirements.txt
+</code></pre>
<p>En espérant vous avoir été utile avec ce billet, je m'en retourne vaquer à mes occupations, et vous rappelle à toutes fins utiles qu'<a href="http://www.akei.com/">Akei</a> serait quand même super contente d'avoir <a href="http://www.akei.com/fr/contact">un coup de fil de votre part</a> pour travailler sur vos chouettes projets en devenir, pourquoi pas en créant plein de <code>virtualenv</code> Python sympas comme tout ;)</p>
<p><strong>Edit&nbsp;:</strong> Prise en compte de la variable d'environnement <code>PIP_RESPECT_VIRTUALENV</code> pour que <code>pip</code> detecte automatiquement la présence d'un environnement virtuel lors de son utilisation (merci Mathieu !)</p>
</section>
@@ -239,7 +207,7 @@
<!-- /container -->
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js"></script>
<script>window.jQuery || document.write('<script src="js/libs/jquery-1.7.1.min.js"><\/script>')</script>
- <script type="text/javascript" src="/static/packed.js?1331882039"></script>
+ <script type="text/javascript" src="/static/packed.js?1333283940"></script>
<script src="//platform.twitter.com/widgets.js" charset="utf-8"></script>
</body>
</html>
View
122 build/code/2010/express/index.html
@@ -7,7 +7,7 @@
<title>A First Look at node.js and Express | Code | Nicolas Perriault</title>
<meta name="description" content="Nicolas Perriault's homepage.">
<meta name="viewport" content="width=device-width">
- <link rel="stylesheet" type="text/css" href="/static/packed.css?1331882038">
+ <link rel="stylesheet" type="text/css" href="/static/packed.css?1333283939">
<link rel="alternate" type="application/rss+xml" href="/code/feed/" title="Code (RSS)">
<link rel="alternate" type="application/rss+xml" href="/photography/feed/" title="Photography (RSS)">
<link rel="alternate" type="application/rss+xml" href="/talks/feed/" title="Talks (RSS)">
@@ -39,91 +39,75 @@
<p>Node is described as an <em>Evented I/O Framework for Google's V8 JavaScript Engine</em>. Think of it as a toolkit to produce high-performance distributed, event-driven and scalable non-blocking network servers. Okay, whatever the way I want to describe the project, it's buzzword-bingo™. Let's say it's mainly about catching events and react accordingly, to make load distribution and parallel processing easier and more effective.</p>
<h3>Installing Node</h3>
<p>Installation on my Mac went smoothly and took nearly two minutes by compiling it from the sources; here's how I did (there might be easier or better ways, I don't really care):</p>
-<div class="codehilite"><pre>$ <span class="n">mkdir</span> <span class="n">tmp</span>
-$ <span class="n">git</span> <span class="n">clone</span> <span class="n">http</span><span class="p">:</span><span class="o">//</span><span class="n">github</span><span class="p">.</span><span class="n">com</span><span class="o">/</span><span class="n">ry</span><span class="o">/</span><span class="n">node</span><span class="p">.</span><span class="n">git</span>
-$ <span class="n">cd</span> <span class="n">node</span>
-$ <span class="o">./</span><span class="n">configure</span> <span class="o">&amp;&amp;</span> <span class="n">make</span> <span class="o">&amp;&amp;</span> <span class="n">sudo</span> <span class="n">make</span> <span class="n">install</span>
-</pre></div>
-
-
+<pre><code>$ mkdir tmp
+$ git clone http://github.com/ry/node.git
+$ cd node
+$ ./configure &amp;&amp; make &amp;&amp; sudo make install
+</code></pre>
<p>You now have access to the <code>node</code> executable available on your system.</p>
<p>A simple example of a Node HTTP server (put the code below in a <code>test.js</code> file):</p>
-<div class="codehilite"><pre><span class="n">var</span> <span class="n">http</span> <span class="p">=</span> <span class="n">require</span><span class="p">(</span><span class="s">&#39;http&#39;</span><span class="p">);</span>
-
-<span class="n">var</span> <span class="n">server</span> <span class="p">=</span> <span class="n">http</span><span class="p">.</span><span class="n">createServer</span><span class="p">(</span><span class="k">function</span><span class="p">(</span><span class="n">req</span><span class="p">,</span> <span class="n">res</span><span class="p">)</span> <span class="p">{</span>
- <span class="n">res</span><span class="p">.</span><span class="n">writeHead</span><span class="p">(</span>200<span class="p">,</span> <span class="p">{</span><span class="s">&#39;Content-Type&#39;</span><span class="p">:</span> <span class="s">&#39;text/plain&#39;</span><span class="p">});</span>
- <span class="n">res</span><span class="p">.</span><span class="n">write</span><span class="p">(</span><span class="s">&#39;Hello World&#39;</span><span class="p">);</span>
- <span class="n">res</span><span class="p">.</span><span class="k">end</span><span class="p">();</span>
-<span class="p">});</span>
-
-<span class="n">server</span><span class="p">.</span><span class="n">listen</span><span class="p">(</span>3000<span class="p">,</span> &quot;127<span class="p">.</span>0<span class="p">.</span>0<span class="p">.</span>1&quot;<span class="p">);</span>
-</pre></div>
+<pre><code>var http = require('http');
+var server = http.createServer(function(req, res) {
+ res.writeHead(200, {'Content-Type': 'text/plain'});
+ res.write('Hello World');
+ res.end();
+});
+server.listen(3000, "127.0.0.1");
+</code></pre>
<p>Then launch the created webserver using the command line:</p>
-<div class="codehilite"><pre>$ <span class="n">node</span> <span class="n">test</span><span class="p">.</span><span class="n">js</span>
-</pre></div>
-
-
+<pre><code>$ node test.js
+</code></pre>
<p>And point your browser at <code>http://127.0.0.1:3000</code> to get printed <code>Hello World</code>. Neat, huh?</p>
<h3>Introducing Express, a Web Framework on top of Node</h3>
<p><a href="http://expressjs.com/">Express</a> is a Web framework built on top of Node, HTTP and <a href="http://github.com/senchalabs/connect">Connect</a>, allowing easy creation of full-fledged Web applications. It has <a href="http://expressjs.com/guide.html#Routing">routing</a>, handles <a href="http://expressjs.com/guide.html#Configuration">environments</a> as well as several <a href="http://expressjs.com/guide.html#Template-Engines">template engines</a> and <a href="http://expressjs.com/guide.html">much more</a>.</p>
<p>Installation is as easy as Node's one, so here we go:</p>
-<div class="codehilite"><pre>$ <span class="n">git</span> <span class="n">clone</span> <span class="n">http</span><span class="p">:</span><span class="o">//</span><span class="n">github</span><span class="p">.</span><span class="n">com</span><span class="o">/</span><span class="n">visionmedia</span><span class="o">/</span><span class="n">express</span><span class="p">.</span><span class="n">git</span>
-$ <span class="n">cd</span> <span class="n">express</span>
-$ <span class="n">git</span> <span class="n">submodule</span> <span class="n">update</span> <span class="o">--</span><span class="n">init</span>
-$ <span class="n">sudo</span> <span class="n">make</span> <span class="n">install</span> <span class="o">&amp;&amp;</span> <span class="n">sudo</span> <span class="n">make</span> <span class="n">install</span><span class="o">-</span><span class="n">support</span>
-</pre></div>
-
-
+<pre><code>$ git clone http://github.com/visionmedia/express.git
+$ cd express
+$ git submodule update --init
+$ sudo make install &amp;&amp; sudo make install-support
+</code></pre>
<p>That's it. You can now write your own test application, eg. in a new <code>hello.js</code> file:</p>
-<div class="codehilite"><pre><span class="n">var</span> <span class="n">app</span> <span class="p">=</span> <span class="n">require</span><span class="p">(</span><span class="s">&#39;express&#39;</span><span class="p">).</span><span class="n">createServer</span><span class="p">();</span>
+<pre><code>var app = require('express').createServer();
-<span class="n">app</span><span class="p">.</span><span class="n">get</span><span class="p">(</span><span class="s">&#39;/&#39;</span><span class="p">,</span> <span class="k">function</span><span class="p">(</span><span class="n">req</span><span class="p">,</span> <span class="n">res</span><span class="p">){</span>
- <span class="n">res</span><span class="p">.</span><span class="n">send</span><span class="p">(</span><span class="s">&#39;Hello World&#39;</span><span class="p">);</span>
-<span class="p">});</span>
+app.get('/', function(req, res){
+ res.send('Hello World');
+});
-<span class="n">app</span><span class="p">.</span><span class="n">get</span><span class="p">(</span><span class="s">&#39;/hello/:name&#39;</span><span class="p">,</span> <span class="k">function</span><span class="p">(</span><span class="n">req</span><span class="p">,</span> <span class="n">res</span><span class="p">){</span>
- <span class="n">res</span><span class="p">.</span><span class="n">send</span><span class="p">(</span><span class="s">&#39;Hello &#39;</span> <span class="o">+</span> <span class="n">req</span><span class="p">.</span><span class="n">param</span><span class="p">(</span><span class="s">&#39;name&#39;</span><span class="p">)</span> <span class="o">+</span> <span class="s">&#39;!&#39;</span><span class="p">);</span>
-<span class="p">});</span>
-
-<span class="n">app</span><span class="p">.</span><span class="n">listen</span><span class="p">(</span>3000<span class="p">,</span> &quot;127<span class="p">.</span>0<span class="p">.</span>0<span class="p">.</span>1&quot;<span class="p">);</span>
-
-<span class="n">console</span><span class="p">.</span><span class="nb">log</span><span class="p">(</span><span class="s">&#39;Server running at http://127.0.0.1:3000/&#39;</span><span class="p">);</span>
-</pre></div>
+app.get('/hello/:name', function(req, res){
+ res.send('Hello ' + req.param('name') + '!');
+});
+app.listen(3000, "127.0.0.1");
+console.log('Server running at http://127.0.0.1:3000/');
+</code></pre>
<p>Launch your webapp server by the command line:</p>
-<div class="codehilite"><pre>$ <span class="n">node</span> <span class="n">hello</span><span class="p">.</span><span class="n">js</span>
-</pre></div>
-
-
+<pre><code>$ node hello.js
+</code></pre>
<p>Express and will create a Node server listening to the local port 3000, so head your favorite browser to <code>http://127.0.0.1:3000/</code> then <code>http://127.0.0.1:3000/hello/niko</code> to get the picture of what the above code does. Those familiar with Web framework such as rails, django or symfony won't be much disturbed.</p>
<p>Express also ships with an <code>express</code> executable which provides useful commands. To create a new <code>hello</code> application skeleton, just run:</p>
-<div class="codehilite"><pre> $ <span class="n">express</span> <span class="n">hello</span>
- <span class="n">create</span> <span class="p">:</span> <span class="n">hello</span>
- <span class="n">create</span> <span class="p">:</span> <span class="n">hello</span><span class="o">/</span><span class="n">app</span><span class="p">.</span><span class="n">js</span>
- <span class="n">create</span> <span class="p">:</span> <span class="n">hello</span><span class="o">/</span><span class="n">logs</span>
- <span class="n">create</span> <span class="p">:</span> <span class="n">hello</span><span class="o">/</span><span class="n">public</span><span class="o">/</span><span class="n">javascripts</span>
- <span class="n">create</span> <span class="p">:</span> <span class="n">hello</span><span class="o">/</span><span class="n">pids</span>
- <span class="n">create</span> <span class="p">:</span> <span class="n">hello</span><span class="o">/</span><span class="n">public</span><span class="o">/</span><span class="n">stylesheets</span>
- <span class="n">create</span> <span class="p">:</span> <span class="n">hello</span><span class="o">/</span><span class="n">public</span><span class="o">/</span><span class="n">stylesheets</span><span class="o">/</span><span class="n">style</span><span class="p">.</span><span class="n">less</span>
- <span class="n">create</span> <span class="p">:</span> <span class="n">hello</span><span class="o">/</span><span class="n">public</span><span class="o">/</span><span class="n">images</span>
- <span class="n">create</span> <span class="p">:</span> <span class="n">hello</span><span class="o">/</span><span class="n">views</span><span class="o">/</span><span class="n">partials</span>
- <span class="n">create</span> <span class="p">:</span> <span class="n">hello</span><span class="o">/</span><span class="n">views</span><span class="o">/</span><span class="n">layout</span><span class="p">.</span><span class="n">jade</span>
- <span class="n">create</span> <span class="p">:</span> <span class="n">hello</span><span class="o">/</span><span class="n">views</span><span class="o">/</span><span class="n">index</span><span class="p">.</span><span class="n">jade</span>
- <span class="n">create</span> <span class="p">:</span> <span class="n">hello</span><span class="o">/</span><span class="n">test</span>
- <span class="n">create</span> <span class="p">:</span> <span class="n">hello</span><span class="o">/</span><span class="n">test</span><span class="o">/</span><span class="n">app</span><span class="p">.</span><span class="n">test</span><span class="p">.</span><span class="n">js</span>
-</pre></div>
-
-
+<pre><code> $ express hello
+ create : hello
+ create : hello/app.js
+ create : hello/logs
+ create : hello/public/javascripts
+ create : hello/pids
+ create : hello/public/stylesheets
+ create : hello/public/stylesheets/style.less
+ create : hello/public/images
+ create : hello/views/partials
+ create : hello/views/layout.jade
+ create : hello/views/index.jade
+ create : hello/test
+ create : hello/test/app.test.js
+</code></pre>
<p>Above command just created an <code>hello</code> project directory where you can cd into and launch the server by its default front controller <code>app.js</code>:</p>
-<div class="codehilite"><pre>$ <span class="n">cd</span> <span class="n">hello</span>
-$ <span class="n">node</span> <span class="n">app</span><span class="p">.</span><span class="n">js</span>
-<span class="n">Express</span> <span class="n">server</span> <span class="n">listening</span> <span class="n">on</span> <span class="n">port</span> 3000
-</pre></div>
-
-
+<pre><code>$ cd hello
+$ node app.js
+Express server listening on port 3000
+</code></pre>
<p>Note that the generated project skeleton implies using <a href="jade-lang.com/">Jade</a> as a tremplate engine and the <a href="http://lesscss.org/">Less CSS syntax</a>, while one might want to use something else, which is perfectly possible by <a href="http://expressjs.com/guide.html#Configuration">configuring</a> the project differently.</p>
<p>Next steps documentation will be provided by <a href="http://expressjs.com/guide.html">official Express documentation</a>.</p>
<p>Of course, Express might not be as full-featured as older well-established Web frameworks, but for simple needs it can be pretty easy to setup and deploy, and — probably equally importantly — fun to play with and learn.</p>
@@ -176,7 +160,7 @@
<!-- /container -->
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js"></script>
<script>window.jQuery || document.write('<script src="js/libs/jquery-1.7.1.min.js"><\/script>')</script>
- <script type="text/javascript" src="/static/packed.js?1331882039"></script>
+ <script type="text/javascript" src="/static/packed.js?1333283940"></script>
<script src="//platform.twitter.com/widgets.js" charset="utf-8"></script>
</body>
</html>
View
4 build/code/2010/index.html
@@ -7,7 +7,7 @@
<title>Code | Nicolas Perriault</title>
<meta name="description" content="Nicolas Perriault's homepage.">
<meta name="viewport" content="width=device-width">
- <link rel="stylesheet" type="text/css" href="/static/packed.css?1331882038">
+ <link rel="stylesheet" type="text/css" href="/static/packed.css?1333283939">
<link rel="alternate" type="application/rss+xml" href="/code/feed/" title="Code (RSS)">
<link rel="alternate" type="application/rss+xml" href="/photography/feed/" title="Photography (RSS)">
<link rel="alternate" type="application/rss+xml" href="/talks/feed/" title="Talks (RSS)">
@@ -125,7 +125,7 @@
<!-- /container -->
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js"></script>
<script>window.jQuery || document.write('<script src="js/libs/jquery-1.7.1.min.js"><\/script>')</script>
- <script type="text/javascript" src="/static/packed.js?1331882039"></script>
+ <script type="text/javascript" src="/static/packed.js?1333283940"></script>
<script src="//platform.twitter.com/widgets.js" charset="utf-8"></script>
</body>
</html>
View
58 build/code/2010/pil-install/index.html
@@ -7,7 +7,7 @@
<title>Install PIL within a virtualenv on Snow Leopard | Code | Nicolas Perriault</title>
<meta name="description" content="Nicolas Perriault's homepage.">
<meta name="viewport" content="width=device-width">
- <link rel="stylesheet" type="text/css" href="/static/packed.css?1331882038">
+ <link rel="stylesheet" type="text/css" href="/static/packed.css?1333283939">
<link rel="alternate" type="application/rss+xml" href="/code/feed/" title="Code (RSS)">
<link rel="alternate" type="application/rss+xml" href="/photography/feed/" title="Photography (RSS)">
<link rel="alternate" type="application/rss+xml" href="/talks/feed/" title="Talks (RSS)">
@@ -36,38 +36,34 @@
<section>
<p>As a personal reminder, here's how to install <a href="http://www.pythonware.com/products/pil/">PIL</a> with jpeg and freetype support in a Python <a href="/post/573774396/installer-django-dans-un-environnement-python-virtuel">virtualenv</a> with a little help from <a href="https://github.com/mxcl/homebrew">Homebrew</a>:</p>
-<div class="codehilite"><pre>$ <span class="n">brew</span> <span class="n">install</span> <span class="n">jpeg</span>
-$ <span class="n">wget</span> <span class="n">http</span><span class="p">:</span><span class="o">//</span><span class="n">mirrors</span><span class="p">.</span><span class="n">fe</span><span class="p">.</span><span class="n">up</span><span class="p">.</span><span class="n">pt</span><span class="o">/</span><span class="n">pub</span><span class="o">/</span><span class="n">nongnu</span><span class="o">/</span><span class="n">freetype</span><span class="o">/</span><span class="n">freetype</span><span class="o">-</span>2<span class="p">.</span>4<span class="p">.</span>4<span class="p">.</span><span class="n">tar</span><span class="p">.</span><span class="n">gz</span>
-$ <span class="n">tar</span> <span class="n">xvzf</span> <span class="n">freetype</span><span class="o">-</span>2<span class="p">.</span>4<span class="p">.</span>4<span class="p">.</span><span class="n">tar</span><span class="p">.</span><span class="n">gz</span> <span class="o">&amp;&amp;</span> <span class="n">cd</span> <span class="n">freetype</span><span class="o">-</span>2<span class="p">.</span>4<span class="p">.</span>4
-$ <span class="o">./</span><span class="n">configure</span> <span class="o">&amp;&amp;</span> <span class="n">make</span> <span class="o">&amp;&amp;</span> <span class="n">sudo</span> <span class="n">make</span> <span class="n">install</span>
-$ <span class="n">cd</span> <span class="p">..</span> <span class="o">&amp;&amp;</span> <span class="n">rm</span> <span class="o">-</span><span class="n">rf</span> <span class="n">freetype</span><span class="o">-</span>2<span class="p">.</span>4<span class="p">.</span>4<span class="o">*</span>
-$ <span class="n">mkvirtualenv</span> <span class="n">fubar</span> <span class="o">--</span><span class="n">no</span><span class="o">-</span><span class="n">site</span><span class="o">-</span><span class="n">packages</span>
-<span class="p">(</span><span class="n">fubar</span><span class="p">)</span>$ <span class="n">pip</span> <span class="n">install</span> <span class="n">PIL</span>
-</pre></div>
-
-
+<pre><code>$ brew install jpeg
+$ wget http://mirrors.fe.up.pt/pub/nongnu/freetype/freetype-2.4.4.tar.gz
+$ tar xvzf freetype-2.4.4.tar.gz &amp;&amp; cd freetype-2.4.4
+$ ./configure &amp;&amp; make &amp;&amp; sudo make install
+$ cd .. &amp;&amp; rm -rf freetype-2.4.4*
+$ mkvirtualenv fubar --no-site-packages
+(fubar)$ pip install PIL
+</code></pre>
<p>You should obtain something like this at the end of the installation process:</p>
-<div class="codehilite"><pre><span class="o">--------------------------------------------------------------------</span>
-<span class="n">PIL</span> 1<span class="p">.</span>1<span class="p">.</span>7 <span class="n">SETUP</span> <span class="n">SUMMARY</span>
-<span class="o">--------------------------------------------------------------------</span>
-<span class="n">version</span> 1<span class="