<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/rss2full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><rss xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:sy="http://purl.org/rss/1.0/modules/syndication/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:creativeCommons="http://backend.userland.com/creativeCommonsRssModule" xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" version="2.0">

<channel>
	<title>Luc Stepniewski's Blog</title>
	
	<link>http://www.banquise.org</link>
	<description />
	<lastBuildDate>Tue, 05 Feb 2013 10:20:34 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.5.1</generator>
	
		<atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/rss+xml" href="http://feeds.feedburner.com/LiorGradsteinsBlog" /><feedburner:info uri="liorgradsteinsblog" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://www.banquise.org/?pushpress=hub" /><creativeCommons:license>http://creativecommons.org/licenses/by-sa/3.0/</creativeCommons:license><item>
		<title>Combining jQuery Mobile and Flask-WTF may give you headaches, or why dashes sucks in Python variable names</title>
		<link>http://feedproxy.google.com/~r/LiorGradsteinsBlog/~3/feNFgGi_TXY/</link>
		<comments>http://www.banquise.org/python/combining-jquery-mobile-and-flask-wtf-may-give-you-headaches-or-why-dashes-sucks-in-python-variable-names/#comments</comments>
		<pubDate>Tue, 05 Feb 2013 10:19:18 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[flask]]></category>
		<category><![CDATA[framework]]></category>
		<category><![CDATA[javascript]]></category>
		<category><![CDATA[python]]></category>
		<category><![CDATA[web]]></category>

		<guid isPermaLink="false">http://www.banquise.org/?p=455</guid>
		<description><![CDATA[I thought developing using Flask on the backend and using jQuery on the front-end (navigator) would be quite easy. In fact it is, but there are some small traps that can take you time to resolve. A regular case would be, when developing a form, to use Flask with WTForms (Flask-WTF to the rescue!). No [...]]]></description>
				<content:encoded><![CDATA[<p>I thought developing using <a href="http://flask.pocoo.org/" title="Flask website" class="liexternal">Flask</a> on the backend and using <a href="http://jquerymobile.com/" title="jQuery Mobile website" class="liexternal">jQuery</a> on the front-end (navigator) would be quite easy. In fact it is, but there are some small traps that can take you time to resolve.</p>
<p>A regular case would be, when developing a form, to use Flask with <a href="http://wtforms.simplecodes.com" title="WTForms" class="liexternal">WTForms</a> (<a href="http://packages.python.org/Flask-WTF/" class="liexternal">Flask-WTF</a> to the rescue!). No problem, you end up with some Jinja2 templates like the following:</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="html4strict" style="font-family:monospace;"><span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">form</span> <span style="color: #000066;">action</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;{{url_for('setup')}}&quot;</span> <span style="color: #000066;">method</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;POST&quot;</span>&gt;</span>
 {{form.channel}}
[...]</pre></td></tr></table></div>

<p>Here, you&#8217;re converting the variable &#8220;channel&#8221; which comes from a class defined in the Python Flask code, and thanks to WTForms will convert it to an HTML Select Box. You can also add arguments to that, which will be converted automatically to a pair key/value, for example, you can set {{form.channel(class=&#8217;foobar&#8217;)}}, which will translate in HTML to:</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="html4strict" style="font-family:monospace;"><span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">select</span> <span style="color: #000066;">class</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;foobar&quot;</span> <span style="color: #000066;">name</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;channel&quot;</span> <span style="color: #66cc66;">&#91;</span>...<span style="color: #66cc66;">&#93;</span></span></pre></td></tr></table></div>

<p>The problem begins when you want to use the themes from jQuery, which are named like &#8220;data-theme&#8221;. Notice that cool dash (&#8216;-&#8217;)! It prevents you from using the same syntax in Jinja2, as you can&#8217;t directly use dashes in variable names. Hopefully, Karol Kuczmarski gave me the answer in <a href="https://groups.google.com/forum/?hl=en-GB&amp;fromgroups=#!topic/wtforms/wiUZU01As-Y" class="liexternal">the WTForms related Google Group</a>:</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="html4strict" style="font-family:monospace;">{{ form.channel(**{'data-theme': 'b'}) }}</pre></td></tr></table></div>

<div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/LiorGradsteinsBlog?a=feNFgGi_TXY:VmIBC-J1Luw:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/LiorGradsteinsBlog?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/LiorGradsteinsBlog?a=feNFgGi_TXY:VmIBC-J1Luw:V_sGLiPBpWU"><img src="http://feeds.feedburner.com/~ff/LiorGradsteinsBlog?i=feNFgGi_TXY:VmIBC-J1Luw:V_sGLiPBpWU" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/LiorGradsteinsBlog/~4/feNFgGi_TXY" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://www.banquise.org/python/combining-jquery-mobile-and-flask-wtf-may-give-you-headaches-or-why-dashes-sucks-in-python-variable-names/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		<feedburner:origLink>http://www.banquise.org/python/combining-jquery-mobile-and-flask-wtf-may-give-you-headaches-or-why-dashes-sucks-in-python-variable-names/</feedburner:origLink></item>
		<item>
		<title>Book Review: Tactics Time! 1001 Chess Tactics from the Games of Everyday Chess Players</title>
		<link>http://feedproxy.google.com/~r/LiorGradsteinsBlog/~3/esPSfZCk7EA/</link>
		<comments>http://www.banquise.org/chess/book-review-tactics-time-1001-chess-tactics-from-the-games-of-everyday-chess-players/#comments</comments>
		<pubDate>Mon, 31 Dec 2012 11:22:19 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[chess]]></category>
		<category><![CDATA[review]]></category>

		<guid isPermaLink="false">http://www.banquise.org/?p=451</guid>
		<description><![CDATA[I&#8217;ve been subscribed to Tim Brennan&#8217;s newsletter (sent out every week) for quite some time now, so when he wrote this cool book on chess tactics, I was really delighted.  I was even more delighted when I saw that it is written in collaboration with Anthea Carson. All my kids know her for her animal chess [...]]]></description>
				<content:encoded><![CDATA[<p><a href="http://amzn.to/Vqetnc" class="liimagelink"><img class="alignright size-full wp-image-452" alt="1001tactics" src="http://www.banquise.org/wp-content/uploads/2012/12/1001tactics.jpg" width="107" height="160" /></a>I&#8217;ve been subscribed to <a href="http://tacticstime.com/Newsletter/" title="Tim Brennan's website" class="liexternal">Tim Brennan&#8217;s newsletter</a> (sent out every week) for quite some time now, so when he wrote <a href="http://amzn.to/Vqetnc" title="1001 chess tactics from the Games of Everyday chess players" class="liexternal">this cool book on chess tactics</a>, I was really delighted.  I was even more delighted when I saw that it is written in collaboration with <a href="https://twitter.com/ChessAnimal" class="liexternal">Anthea Carson</a>. All my kids know her for <a href="http://amzn.to/ZMMxOB" title="How to Play Chess Like An Animal" class="liexternal">her animal chess book</a> and specifically for her <a href="http://www.youtube.com/watch?v=c_O09lH9e0g" title="Comparison of Penguin vs Fragon opening" class="liexternal">penguin opening</a> that makes them laugh every time they see it.</p>
<p><em>Tactics Time</em> is a <a href="http://amzn.to/Vqetnc" class="liexternal">nicely formatted Kindle book</a> (but you don&#8217;t need to have a Kindle tablet, you can use <a href="https://play.google.com/store/apps/details?id=com.amazon.kindle" title="Kindle android app" class="liexternal">the android app</a> which works really well), where you will find the exercises and the answers on each next page, which makes it really practical for reviewing the answer (no need to go to the end of the book to find the answer, if you didn&#8217;t figure it out :-) For each solution, an explanation is given to help remember which tactics it relates to.</p>
<p>What I also liked was that the exercises were not invented, but from real tournaments, so these positions are possible in real life, which is really a plus.</p>
<div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/LiorGradsteinsBlog?a=esPSfZCk7EA:OZ0FNZgAJzY:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/LiorGradsteinsBlog?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/LiorGradsteinsBlog?a=esPSfZCk7EA:OZ0FNZgAJzY:V_sGLiPBpWU"><img src="http://feeds.feedburner.com/~ff/LiorGradsteinsBlog?i=esPSfZCk7EA:OZ0FNZgAJzY:V_sGLiPBpWU" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/LiorGradsteinsBlog/~4/esPSfZCk7EA" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://www.banquise.org/chess/book-review-tactics-time-1001-chess-tactics-from-the-games-of-everyday-chess-players/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://www.banquise.org/chess/book-review-tactics-time-1001-chess-tactics-from-the-games-of-everyday-chess-players/</feedburner:origLink></item>
		<item>
		<title>Fail2ban Configuration for NGINX anomalies</title>
		<link>http://feedproxy.google.com/~r/LiorGradsteinsBlog/~3/2Bn1uMUvWec/</link>
		<comments>http://www.banquise.org/security/fail2ban-configuration-nginx-anomalies/#comments</comments>
		<pubDate>Thu, 29 Dec 2011 22:52:52 +0000</pubDate>
		<dc:creator>Lior Gradstein</dc:creator>
				<category><![CDATA[network]]></category>
		<category><![CDATA[security]]></category>
		<category><![CDATA[fail2ban]]></category>
		<category><![CDATA[filter]]></category>
		<category><![CDATA[nginx]]></category>
		<category><![CDATA[regex]]></category>
		<category><![CDATA[rules]]></category>

		<guid isPermaLink="false">http://www.gradstein.info/?p=439</guid>
		<description><![CDATA[Fail2ban is a really cool log analyzer (mostly) that can block ips using several different methods (iptables, ipfw, ip route blackhole, etc.). The problem is that you have to define filters (regexes in fact) that will trigger the ban for each service, because each one has a different way to report anomalies. There are not [...]]]></description>
				<content:encoded><![CDATA[<p>Fail2ban is a really cool log analyzer (mostly) that can block ips using several different methods (iptables, ipfw, ip route blackhole, etc.). The problem is that you have to define filters (regexes in fact) that will trigger the ban for each service, because each one has a different way to report anomalies. There are not so much given examples <a href="http://www.fail2ban.org/wiki/index.php/Fail2ban:Community_Portal" title="Fail2ban community portal" class="liexternal">on the official wiki</a>. On other websites I couldn&#8217;t find anything about nginx filters. Even worse, several <a href="http://codelog.climens.net/2011/02/13/using-fail2ban-with-nginx-in-debian/" title="Example of wrong example" class="liexternal">websites</a> report that you can use the filters defined  for Apache2, which is false, they will <strong>NOT</strong> work, the logs are very different.</p>
<p>For example, here is a trace for a non existent requested resource:</p>
<p><code>2011/12/29 16:13:33 [error] 3212#0: *241787 open() "/opt/foo/default/admin/phpmyadmin/index.php" failed (2: No such file or directory), client: 58.19.239.205, server: , request: "GET //admin/phpmyadmin/index.php HTTP/1.1", host: "88.191.135.71"</code></p>
<p>So, to be able to detect such hack tentative and block it, create a file named nginx-noscript.conf, and put:</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="bash" style="font-family:monospace;"><span style="color: #7a0874; font-weight: bold;">&#91;</span>Definition<span style="color: #7a0874; font-weight: bold;">&#93;</span>
failregex = open\<span style="color: #7a0874; font-weight: bold;">&#40;</span>\<span style="color: #7a0874; font-weight: bold;">&#41;</span> <span style="color: #ff0000;">&quot;/\S*(\.php|\.asp|\.exe|\.pl)\S*&quot;</span> failed.<span style="color: #000000; font-weight: bold;">*</span>client: <span style="color: #000000; font-weight: bold;">&lt;</span>HOST<span style="color: #000000; font-weight: bold;">&gt;</span>,.<span style="color: #000000; font-weight: bold;">*</span>
ignoreregex =</pre></td></tr></table></div>

<p>Then, add its definition in an entry in the /etc/fail2ban/jail.conf:</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="bash" style="font-family:monospace;"><span style="color: #7a0874; font-weight: bold;">&#91;</span>nginx<span style="color: #7a0874; font-weight: bold;">&#93;</span>
enabled = <span style="color: #c20cb9; font-weight: bold;">true</span>
port = http,https
filter = nginx-noscript
logpath = <span style="color: #000000; font-weight: bold;">/</span>var<span style="color: #000000; font-weight: bold;">/</span>log<span style="color: #000000; font-weight: bold;">/</span>nginx<span style="color: #000000; font-weight: bold;">*/*</span>error.log
maxretry = <span style="color: #000000;">6</span></pre></td></tr></table></div>

<p>Here, if there are more than 6 occurences of a failed 404 request in less than 600 seconds (<a href="http://www.fail2ban.org/wiki/index.php/MANUAL_0_8#Jail_Options" title="Fail2ban Jail options" class="liexternal">the default value</a>, modifiable with the &#8216;findtime&#8217; variable), the ip will be added to the ban list.</p>
<div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/LiorGradsteinsBlog?a=2Bn1uMUvWec:Zya6aPean3M:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/LiorGradsteinsBlog?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/LiorGradsteinsBlog?a=2Bn1uMUvWec:Zya6aPean3M:V_sGLiPBpWU"><img src="http://feeds.feedburner.com/~ff/LiorGradsteinsBlog?i=2Bn1uMUvWec:Zya6aPean3M:V_sGLiPBpWU" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/LiorGradsteinsBlog/~4/2Bn1uMUvWec" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://www.banquise.org/security/fail2ban-configuration-nginx-anomalies/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		<feedburner:origLink>http://www.banquise.org/security/fail2ban-configuration-nginx-anomalies/</feedburner:origLink></item>
		<item>
		<title>New version of chess PGN to TeX to PDF converter</title>
		<link>http://feedproxy.google.com/~r/LiorGradsteinsBlog/~3/81LQk9ZJXg4/</link>
		<comments>http://www.banquise.org/python/version-chess-pgn-tex-pdf-converter/#comments</comments>
		<pubDate>Tue, 28 Dec 2010 01:37:08 +0000</pubDate>
		<dc:creator>Lior Gradstein</dc:creator>
				<category><![CDATA[chess]]></category>
		<category><![CDATA[kid]]></category>
		<category><![CDATA[latex]]></category>
		<category><![CDATA[python]]></category>
		<category><![CDATA[children]]></category>
		<category><![CDATA[convert]]></category>
		<category><![CDATA[converter]]></category>
		<category><![CDATA[game]]></category>
		<category><![CDATA[learning]]></category>
		<category><![CDATA[mate in one]]></category>
		<category><![CDATA[pdf]]></category>
		<category><![CDATA[pgn]]></category>
		<category><![CDATA[skak]]></category>
		<category><![CDATA[skaknew]]></category>
		<category><![CDATA[tetex]]></category>
		<category><![CDATA[tex]]></category>
		<category><![CDATA[tex live]]></category>

		<guid isPermaLink="false">http://www.gradstein.info/?p=418</guid>
		<description><![CDATA[OK, I&#8217;m shameful. After fighting with Scid&#8217;s exporter, and then correcting bugs in pgn2ltx&#8217;s source, I finally decided to take a look at that PGN file format. And guess what? It&#8217;s already composed of FEN notation. And guess what? that super-über cool new skaknew module for LaTeX gets its input as FEN!! So, if I [...]]]></description>
				<content:encoded><![CDATA[<p>OK, I&#8217;m shameful. After fighting with <a href="http://scid.sourceforge.net/" class="liexternal">Scid&#8217;s</a> exporter, and then correcting bugs in pgn2ltx&#8217;s source, I finally decided to take a look at that <a href="http://en.wikipedia.org/wiki/Portable_Game_Notation" rel="nofollow" class="liwikipedia">PGN</a> file format. And guess what? It&#8217;s already composed of <a href="http://en.wikipedia.org/wiki/Forsyth%E2%80%93Edwards_Notation" rel="nofollow" class="liwikipedia">FEN</a> notation. And guess what? that super-über cool new skaknew module for LaTeX gets its input as FEN!!</p>
<p><span id="more-418"></span></p>
<p>So, if I had a working brain 1 week ago (at least), I would write a small python program that would eat that PGN and make it into a nicely formatted skaknew TeX formatted file!</p>
<p>Here is that much wanted program, that took just 5 minutes to write:</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
</pre></td><td class="code"><pre class="python" style="font-family:monospace;"><span style="color: #808080; font-style: italic;">#!/usr/bin/env python</span>
<span style="color: #808080; font-style: italic;"># -*- coding: utf-8 -*-</span>
<span style="color: #808080; font-style: italic;">#</span>
<span style="color: #808080; font-style: italic;"># vim:syntax=python:sw=4:ts=4:expandtab</span>
<span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">sys</span><span style="color: #66cc66;">,</span><span style="color: #dc143c;">re</span>
&nbsp;
HEADER<span style="color: #66cc66;">=</span><span style="color: #483d8b;">&quot;&quot;&quot;<span style="color: #000099; font-weight: bold;">\</span>
<span style="color: #000099; font-weight: bold;">\\</span>documentclass[10pt,twocolumn]{article}
&nbsp;
<span style="color: #000099; font-weight: bold;">\\</span>usepackage[skaknew]{chessboard,skak}
%<span style="color: #000099; font-weight: bold;">\\</span>usepackage[ps]{skak}
<span style="color: #000099; font-weight: bold;">\\</span>usepackage{latexsym}
<span style="color: #000099; font-weight: bold;">\\</span>usepackage[utf8]{inputenc}
<span style="color: #000099; font-weight: bold;">\\</span>font<span style="color: #000099; font-weight: bold;">\\</span>logo=logo10
<span style="color: #000099; font-weight: bold;">\\</span>font<span style="color: #000099; font-weight: bold;">\\</span>sknf=SkakNew-Figurine
<span style="color: #000099; font-weight: bold;">\\</span>font<span style="color: #000099; font-weight: bold;">\\</span>sknfbx=SkakNew-FigurineBold
<span style="color: #000099; font-weight: bold;">\\</span>font<span style="color: #000099; font-weight: bold;">\\</span>skndia=SkakNew-DiagramT
<span style="color: #000099; font-weight: bold;">\\</span>def<span style="color: #000099; font-weight: bold;">\\</span>Metafont{<span style="color: #000099; font-weight: bold;">\\</span>mbox{<span style="color: #000099; font-weight: bold;">\\</span>logo METAFONT}}
&nbsp;
<span style="color: #000099; font-weight: bold;">\\</span>usepackage{a4wide}
%<span style="color: #000099; font-weight: bold;">\\</span>usepackage{geometry} % to change the page dimensions
%<span style="color: #000099; font-weight: bold;">\\</span>geometry{a4paper}
%%<span style="color: #000099; font-weight: bold;">\\</span>geometry{margin=5in}
%<span style="color: #000099; font-weight: bold;">\\</span>geometry{portrait}
&nbsp;
<span style="color: #000099; font-weight: bold;">\\</span>usepackage{fancyhdr} % This should be set AFTER setting up the page geometry
<span style="color: #000099; font-weight: bold;">\\</span>pagestyle{fancy} % options: empty , plain , fancy
<span style="color: #000099; font-weight: bold;">\\</span>renewcommand{<span style="color: #000099; font-weight: bold;">\\</span>headrulewidth}{0pt} % customise the layout...
<span style="color: #000099; font-weight: bold;">\\</span>lhead{}<span style="color: #000099; font-weight: bold;">\\</span>chead{}<span style="color: #000099; font-weight: bold;">\\</span>rhead{}
<span style="color: #000099; font-weight: bold;">\\</span>lfoot{}<span style="color: #000099; font-weight: bold;">\\</span>cfoot{<span style="color: #000099; font-weight: bold;">\\</span>thepage}<span style="color: #000099; font-weight: bold;">\\</span>rfoot{}
&nbsp;
<span style="color: #000099; font-weight: bold;">\\</span>frenchspacing
<span style="color: #000099; font-weight: bold;">\\</span>begin{document}
&quot;&quot;&quot;</span>
&nbsp;
TEMPLATE<span style="color: #66cc66;">=</span><span style="color: #483d8b;">&quot;&quot;&quot;<span style="color: #000099; font-weight: bold;">\</span>
<span style="color: #000099; font-weight: bold;">\\</span>chessboard[
   setfen=%s,
   ]
&nbsp;
&quot;&quot;&quot;</span>
&nbsp;
END_DOC <span style="color: #66cc66;">=</span> <span style="color: #483d8b;">&quot;<span style="color: #000099; font-weight: bold;">\\</span>end{document}&quot;</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">def</span> main<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>:
    pre <span style="color: #66cc66;">=</span> <span style="color: #dc143c;">sys</span>.<span style="color: black;">argv</span><span style="color: black;">&#91;</span><span style="color: #ff4500;">1</span><span style="color: black;">&#93;</span>.<span style="color: black;">split</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'.'</span><span style="color: #66cc66;">,</span><span style="color: #ff4500;">2</span><span style="color: black;">&#41;</span><span style="color: black;">&#91;</span><span style="color: #ff4500;">0</span><span style="color: black;">&#93;</span>
    output_file <span style="color: #66cc66;">=</span> <span style="color: #008000;">open</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;%s-out.tex&quot;</span> % pre<span style="color: #66cc66;">,</span><span style="color: #483d8b;">'w'</span><span style="color: black;">&#41;</span>
&nbsp;
    <span style="color: #808080; font-style: italic;"># First, write the header</span>
    output_file.<span style="color: black;">write</span><span style="color: black;">&#40;</span>HEADER<span style="color: black;">&#41;</span>
&nbsp;
    expr <span style="color: #66cc66;">=</span> <span style="color: #dc143c;">re</span>.<span style="color: #008000;">compile</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'^<span style="color: #000099; font-weight: bold;">\[</span>FEN &quot;([^&quot;]+)&quot;<span style="color: #000099; font-weight: bold;">\]</span>'</span><span style="color: black;">&#41;</span>
    <span style="color: #ff7700;font-weight:bold;">for</span> line <span style="color: #ff7700;font-weight:bold;">in</span> <span style="color: #008000;">open</span><span style="color: black;">&#40;</span><span style="color: #dc143c;">sys</span>.<span style="color: black;">argv</span><span style="color: black;">&#91;</span><span style="color: #ff4500;">1</span><span style="color: black;">&#93;</span><span style="color: black;">&#41;</span>.<span style="color: black;">xreadlines</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>:
        result <span style="color: #66cc66;">=</span> expr.<span style="color: black;">search</span><span style="color: black;">&#40;</span>line<span style="color: black;">&#41;</span>
        <span style="color: #ff7700;font-weight:bold;">if</span> result:
            output_file.<span style="color: black;">write</span><span style="color: black;">&#40;</span>TEMPLATE % result.<span style="color: black;">group</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">1</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
&nbsp;
    output_file.<span style="color: black;">write</span><span style="color: black;">&#40;</span>END_DOC<span style="color: black;">&#41;</span>
    output_file.<span style="color: black;">close</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">if</span> __name__ <span style="color: #66cc66;">==</span> <span style="color: #483d8b;">'__main__'</span>:
    main<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span></pre></td></tr></table></div>

<p>And the best of all, is that I have now full control in its output (well, in my light LaTeX&#8217;s knowledge limits). So now I can add a marker to tell which turn it is (little colored square box next to each game). You wll still get <a href="http://www.gradstein.info/wp-content/uploads/mate_in_one-out.pdf" class="lipdf">196 pages</a>, that is 1171 mate in one diagrams to solve.</p>
<p><a href="http://www.gradstein.info/wp-content/uploads/2010/12/pdf-screen.png" class="liimagelink"><img class="aligncenter size-full wp-image-419" title="Example of chess diagram output" src="http://www.gradstein.info/wp-content/uploads/2010/12/pdf-screen.png" alt="" width="462" height="690" /></a></p>
<p>So, to summarize, here are the files:</p>
<ul>
<li>The <a href="http://www.gradstein.info/wp-content/uploads/mate_in_one-out.pdf" class="lipdf">generated PDF</a></li>
<li>The intermediate file, <a href="http://www.gradstein.info/wp-content/uploads/mate_in_one-out.tex" class="liexternal">in TeX format</a></li>
<li>The original file, in <a href="http://www.gradstein.info/wp-content/uploads/mate_in_one.pgn.gz" class="lizip">PGN format</a></li>
</ul>
<div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/LiorGradsteinsBlog?a=81LQk9ZJXg4:w7QdStmdnPM:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/LiorGradsteinsBlog?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/LiorGradsteinsBlog?a=81LQk9ZJXg4:w7QdStmdnPM:V_sGLiPBpWU"><img src="http://feeds.feedburner.com/~ff/LiorGradsteinsBlog?i=81LQk9ZJXg4:w7QdStmdnPM:V_sGLiPBpWU" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/LiorGradsteinsBlog/~4/81LQk9ZJXg4" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://www.banquise.org/python/version-chess-pgn-tex-pdf-converter/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		<feedburner:origLink>http://www.banquise.org/python/version-chess-pgn-tex-pdf-converter/</feedburner:origLink></item>
		<item>
		<title>Updated mate-in-one document, now includes chess coordinates</title>
		<link>http://feedproxy.google.com/~r/LiorGradsteinsBlog/~3/oQ1x7FCdIBE/</link>
		<comments>http://www.banquise.org/kid/updated-mate-in-one-document-includes-coordinates/#comments</comments>
		<pubDate>Mon, 27 Dec 2010 23:18:18 +0000</pubDate>
		<dc:creator>Lior Gradstein</dc:creator>
				<category><![CDATA[chess]]></category>
		<category><![CDATA[kid]]></category>
		<category><![CDATA[latex]]></category>
		<category><![CDATA[checkmate]]></category>
		<category><![CDATA[coordinates]]></category>
		<category><![CDATA[échecs]]></category>
		<category><![CDATA[mate]]></category>
		<category><![CDATA[mate in one]]></category>
		<category><![CDATA[Portable Game Notation]]></category>

		<guid isPermaLink="false">http://www.gradstein.info/?p=415</guid>
		<description><![CDATA[Update: A new updated version of the PDF is available, which includes which side to play. After a request to have coordinates on the board, to be able to write answers (a really nice idea, especially that Ido begins writing), I noticed I couldn&#8217;t do it so easily, because the LaTeX module (chess12) didn&#8217;t support [...]]]></description>
				<content:encoded><![CDATA[<p><a href="http://www.gradstein.info/wp-content/uploads/2010/12/932337_chessman.jpg" class="liimagelink"><img class="size-thumbnail wp-image-417 alignright" title="Chess Knights" src="http://www.gradstein.info/wp-content/uploads/2010/12/932337_chessman-150x150.jpg" alt="" width="150" height="150" /></a><strong>Update:</strong> <em>A <a href="/python/version-chess-pgn-tex-pdf-converter/" class="liinternal">new updated version of the PDF is available</a>, which includes which side to play.</em></p>
<p>After a request to have coordinates on the board, to be able to write answers (a really nice idea, especially that Ido begins writing), I noticed I couldn&#8217;t do it so easily, because the LaTeX module (chess12) didn&#8217;t support that. What a disappointment!</p>
<p>And the only way I had for converting from PGN to TeX was through <a href="http://scid.sourceforge.net/" class="liexternal">Scid</a> (still cool, still being developed), but supporting only exports to <a href="http://scid.sourceforge.net/help/LaTeX.html" class="liexternal">TeX with chess12 module</a>. Fortunately, <a href="https://launchpad.net/~dl9obn" class="liexternal">Dirk Baechle</a> wrote a tool to convert directly from PGN format to TeX, using his tool <a href="http://pgn2ltx.sourceforge.net/" class="liexternal">pgn2ltx</a>. That tool, written in C++ hasn&#8217;t been updated since 2003, so after a small patch to the source, it worked!</p>
<p>And the best part, is that it generates TeX files for the <a href="http://www.ctan.org/tex-archive/fonts/chess/skaknew/" class="liexternal">skak module</a>, the best alternative to the old, dead chess12 module.</p>
<p><span id="more-415"></span></p>
<p>So, if you wan to generate yourself the PDF, here is my procedure:</p>
<ul>
<li>First, download the pgn2ltx zip file and uncompress it</li>
<li>Patch it with the following diff file:</li>
</ul>

<div class="wp_syntax"><table><tr><td class="code"><pre class="diff" style="font-family:monospace;"><span style="color: #888822;">--- pgn2ltx.cpp.ori 2010-12-27 21:06:56.000000000 +0100</span>
<span style="color: #888822;">+++ pgn2ltx.cpp 2010-12-27 21:07:10.000000000 +0100</span>
/*------------------------------------------------------------- Includes */
#include &lt;iostream&gt;
<span style="color: #00b000;">+#include &lt;cstring&gt;</span>
#include &lt;string&gt;
#include &lt;fstream&gt;
#include &lt;sstream&gt;</pre></td></tr></table></div>

<p>In fact, just add the <strong>#include &lt;cstring&gt;</strong> besides the other includes.</p>
<div>
<ul>
<li>Now just compile it (you need g++ and usual compilation tools like make).</li>
<li>Download the <a href="http://www.gradstein.info/static/mate_in_one.pgn.gz" class="lizip">mate-in-one PGN database</a> I have in my <a href="http://www.gradstein.info/kid/easy-chess-games-for-kids-mate-in-one" class="liexternal">previous article</a> (no way to get the original, the web page we I found it was erased).</li>
<li>Generate the TeX file (did I tell you that <em><strong>you need the TeX Live distribution</strong></em>, which includes by default the skak module?) with the following command:</li>
</ul>
</div>

<div class="wp_syntax"><table><tr><td class="code"><pre class="bash" style="font-family:monospace;">.<span style="color: #000000; font-weight: bold;">/</span>pgn2ltx  <span style="color: #000000; font-weight: bold;">&lt;</span> mate_in_one.pgn  <span style="color: #000000; font-weight: bold;">&gt;</span> temp.tex</pre></td></tr></table></div>

<p>Now, if you generate your PDF file with that temp.tex file, you&#8217;ll get just one diagram per page, and horrible text placement, so I modified the header to remove the useless text and also remove the answers. That makes space for 6 diagrams on each page.</p>
<p>I used this grep command to remove the text:</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="bash" style="font-family:monospace;"><span style="color: #c20cb9; font-weight: bold;">cat</span> temp.tex <span style="color: #000000; font-weight: bold;">|</span><span style="color: #c20cb9; font-weight: bold;">grep</span> <span style="color: #660033;">-v</span> <span style="color: #ff0000;">&quot;White to Move and Mate in One&quot;</span> <span style="color: #000000; font-weight: bold;">|</span><span style="color: #c20cb9; font-weight: bold;">grep</span> <span style="color: #660033;">-v</span> mate <span style="color: #000000; font-weight: bold;">|</span> <span style="color: #c20cb9; font-weight: bold;">grep</span> <span style="color: #660033;">-v</span> mainline <span style="color: #000000; font-weight: bold;">&gt;</span> temp2.tex</pre></td></tr></table></div>

<p>Replace the header with the following :</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="latex" style="font-family:monospace;"><span style="color: #E02020; ">\</span><span style="color: #800000;">documentclass</span><span style="color: #E02020; ">[</span><span style="color: #C08020; font-weight: normal;">10pt,twocolumn</span><span style="color: #E02020; ">]{</span><span style="color: #2020C0; font-weight: normal;">article<span style="color: #E02020; ">}</span>
&nbsp;
<span style="color: #E02020; ">\</span><span style="color: #800000;">usepackage</span><span style="color: #E02020; ">[</span><span style="color: #C08020; font-weight: normal;">ps</span><span style="color: #E02020; ">]{</span>skak<span style="color: #E02020; ">}</span>
&nbsp;
<span style="color: #E02020; ">\</span><span style="color: #800000;">usepackage</span><span style="color: #E02020; ">{</span>latexsym<span style="color: #E02020; ">}</span>
<span style="color: #E02020; ">\</span><span style="color: #800000;">usepackage</span><span style="color: #E02020; ">[</span><span style="color: #C08020; font-weight: normal;">utf8</span><span style="color: #E02020; ">]{</span>inputenc<span style="color: #E02020; ">}\</span><span style="color: #800000;">usepackage</span><span style="color: #E02020; ">{</span>a4wide<span style="color: #E02020; ">}</span>
<span style="color: #E02020; ">\</span><span style="color: #800000;">usepackage</span>{fancyhdr</span><span style="color: #E02020; ">}</span> <span style="color: #2C922C; font-style: italic;">% This should be set AFTER setting up the page geometry</span>
<span style="color: #E02020; ">\</span><span style="color: #800000;">pagestyle</span><span style="color: #E02020; ">{</span><span style="color: #2020C0; font-weight: normal;">fancy</span><span style="color: #E02020; ">}</span> <span style="color: #2C922C; font-style: italic;">% options: empty , plain , fancy</span>
<span style="color: #E02020; ">\</span><span style="color: #800000;">renewcommand</span><span style="color: #E02020; ">{</span><span style="color: #2020C0; font-weight: normal;"><span style="color: #800000; font-weight: normal;">\headrulewidth</span>}{0pt</span><span style="color: #E02020; ">}</span> <span style="color: #2C922C; font-style: italic;">% customise the layout...</span>
<span style="color: #800000; font-weight: normal;">\lhead</span><span style="color: #E02020; ">{</span><span style="color: #2020C0; font-weight: normal;">}<span style="color: #800000; font-weight: normal;">\chead</span><span style="color: #E02020; ">{}</span><span style="color: #800000; font-weight: normal;">\rhead</span><span style="color: #E02020; ">{}</span>
<span style="color: #800000; font-weight: normal;">\lfoot</span><span style="color: #E02020; ">{}</span><span style="color: #800000; font-weight: normal;">\cfoot</span><span style="color: #E02020; ">{</span><span style="color: #800000; font-weight: normal;">\thepage</span><span style="color: #E02020; ">}</span><span style="color: #800000; font-weight: normal;">\rfoot</span>{</span><span style="color: #E02020; ">}</span></pre></td></tr></table></div>

<p>Here is the <a href="http://www.gradstein.info/wp-content/uploads/new-mate-in-one.pdf" class="lipdf">result, 196 pages of mate in one</a>! (<a href="http://www.gradstein.info/wp-content/uploads/new-mate-in-one.tex" class="liexternal">here is the .tex file</a>, if someone is interested)</p>
<p>Note: There are two problems left.</p>
<ul>
<li>First is that when generating the PDF, I get a lot of &#8220;<strong>Underfull \vbox (badness 10000) has occurred while \output is active</strong>&#8220;. If a LaTeX expert can take a look&#8230;</li>
<li>Second problem, I just noticed that some diagrams have the Black mate in one. I thought there were only White mate in one. So there is no way to know whose turn it is. A solution to this is to use a small coloredbox with the side to play. I think the skak module supports it. Some r<a href="ftp://ftp.inria.fr/pub/TeX/CTAN/fonts/chess/skaknew/SkakNew.pdf" class="lipdf">eading in perspective</a>&#8230;</li>
</ul>
<div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/LiorGradsteinsBlog?a=oQ1x7FCdIBE:-YGYF_95z9M:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/LiorGradsteinsBlog?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/LiorGradsteinsBlog?a=oQ1x7FCdIBE:-YGYF_95z9M:V_sGLiPBpWU"><img src="http://feeds.feedburner.com/~ff/LiorGradsteinsBlog?i=oQ1x7FCdIBE:-YGYF_95z9M:V_sGLiPBpWU" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/LiorGradsteinsBlog/~4/oQ1x7FCdIBE" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://www.banquise.org/kid/updated-mate-in-one-document-includes-coordinates/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://www.banquise.org/kid/updated-mate-in-one-document-includes-coordinates/</feedburner:origLink></item>
		<item>
		<title>Auto-provisioning with Asterisk and ST2030 Technicolor/Thomson phones</title>
		<link>http://feedproxy.google.com/~r/LiorGradsteinsBlog/~3/SZtsjdgSJOs/</link>
		<comments>http://www.banquise.org/software/asterisk/auto-provisioning-asterisk-st2030-technicolorthomson-phones/#comments</comments>
		<pubDate>Mon, 27 Dec 2010 13:45:03 +0000</pubDate>
		<dc:creator>Lior Gradstein</dc:creator>
				<category><![CDATA[asterisk]]></category>
		<category><![CDATA[software]]></category>
		<category><![CDATA[voip]]></category>
		<category><![CDATA[automatic]]></category>
		<category><![CDATA[autoprovisioning]]></category>
		<category><![CDATA[deployment]]></category>
		<category><![CDATA[dhcp]]></category>
		<category><![CDATA[http server]]></category>
		<category><![CDATA[install]]></category>
		<category><![CDATA[provisioning]]></category>
		<category><![CDATA[sip]]></category>
		<category><![CDATA[sip phones]]></category>
		<category><![CDATA[Technicolor]]></category>
		<category><![CDATA[tftp]]></category>
		<category><![CDATA[Thomson]]></category>
		<category><![CDATA[vlan]]></category>

		<guid isPermaLink="false">http://www.gradstein.info/?p=411</guid>
		<description><![CDATA[An introduction to the ST2030 The ST2030 is one of the few SIP phones distributed by Thomson (now changed name to Technicolor). In fact there are only 2 models: the ST2020, and the ST2030, and also a new one, the TB30, which is the successor to the ST2030. The ST2030 is supposed to have an [...]]]></description>
				<content:encoded><![CDATA[<h2 class="title">An introduction to the ST2030</h2>
<p>The ST2030 is one of the few SIP phones distributed by Thomson (now changed name to Technicolor). In fact there are only 2 models: the ST2020, and the ST2030, and also a new one, the TB30, which is the successor to the ST2030. The ST2030 is supposed to have an End-of-Life set to the end of this year (2010), but I read that its EOL has been extended to the end of 2012.<br />
In my personal experience, I think the ST2030 has the best price/functionalities/quality ratio. It has features like:</p>
<ul>
<li> PoE (Power over Ethernet).</li>
<li>Headphone plug with a button on the phone to pickup with the headphone (or if you have a compatible headphone, pickup directly with a button on the headphone).</li>
<li>XML based Directory support, that you can interface with a remote HTTP server.</li>
<li>4 differents lines/profiles (but not at the same time).</li>
<li>BLF (Busy Lamp Fields) to monitor other&#8217;s phone status (if they are using their phone, and even possibility to intercept a call).</li>
<li>Full compatibilty with Asterisk (tested on Asterisk 1.6+ and 1.8+).</li>
<li>Auto-provisioning with support for TFTP but also for HTTP/HTTPS, which simplifies quite a lot the provisioning configuration.</li>
</ul>
<p>In this document, we&#8217;ll see the auto-provisioning process through DHCP+HTTP.</p>
<p><span id="more-411"></span></p>
<p>The main web pages related on the ST2030 are the <a href="http://www.voip-info.org/wiki/view/Thomson+ST2030" class="liexternal">Voip-info.org</a> pages and the <a href="http://technicolorbroadbandpartner.com/telephony-solutions/products/product-detail.php?id=87" class="liexternal">official Technicolor/Thomson web page</a>.</p>
<h2>Requirements</h2>
<ul>
<li>Linux</li>
<li>Asterisk (1.8+)</li>
<li>Technicolor ST2030 phones</li>
<li>DHCP server</li>
<li>HTTP server (Apache, nginx)</li>
</ul>
<p><span style="font-size: 26px; line-height: 28px;">Manual upgrade of the Boot, DSP and APP firmware</span></p>
<ul>
<li>Boot your phone (yes it&#8217;s very long, 5+ minutes)</li>
<li>Long press the &#8216;menu&#8217; button, which will display the phone&#8217;s ip address</li>
</ul>
<p><a href="http://www.gradstein.info/wp-content/uploads/2010/12/300px-St2030_1.jpg" class="liimagelink"><img class="aligncenter size-full wp-image-412" title="Main console of ST2030 phones" src="http://www.gradstein.info/wp-content/uploads/2010/12/300px-St2030_1.jpg" alt="" width="300" height="271" /></a></p>
<ul>
<li>Connect to http://your_ip/admin.html and enter &#8216;<strong>administrator</strong>&#8216; as login and <strong>784518</strong> as password (the default)</li>
<li>Finally go to &#8216;Utility&#8217; tab, and upload the <strong>v2030_boot_v111.zz</strong>, <strong>v2030_dsp_R11.1_SED_v320.zz</strong> and <strong>v2030SG.R11.1.SED.100804.2.72.2.zz</strong> files (each one needs to reboot your phone, it will take a loooooong time :-)</li>
</ul>
<p>To verify that you&#8217;ve correctly upgraded your phone, go to the admin Home page, you should get something like:</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="yaml" style="font-family:monospace;"><span style="color: green;">H/W Version</span><span style="font-weight: bold; color: brown;">: </span>	V5<span style="color: green;">
 Boot Version</span><span style="font-weight: bold; color: brown;">: </span>	V1.11<span style="color: green;">
 DSP Version</span><span style="font-weight: bold; color: brown;">: </span>	V3.20<span style="color: green;">
 APP Version</span><span style="font-weight: bold; color: brown;">: </span>	V2.72</pre></td></tr></table></div>

<p><span style="font-size: 26px; line-height: 28px;">Deploying ST2030 IP phones using DHCP and HTTP</span></p>
<p>This is called auto-provisioning. Normally, one use DHCP/PXE/BOOTP + TFTP to deploy servers, but it is so slow, unreliable, and the tftp protocol is so primitive, that it gets really hard when you need to deploy different phones.</p>
<p>Today, I&#8217;ll show you how to deploy ST2030 phones with only DHCP and HTTP servers, nothing more. The most useful documentation you&#8217;ll need is the &#8220;official&#8221; doc named &#8220;Auto provisioning and customization for IP Phone ST2030 and ST2022, November 16, 2009&#8243;. You can find it in the latest zip file (currently &#8220;<a href="http://technicolorbroadbandpartner.com/telephony-solutions/products/product-detail.php?id=87" class="liexternal">ST2030 SIP firmware and documents v2.72</a>&#8220;.<br />
The latest versions of these phones support provisioning not only by TFTP, but also by HTTP. I don&#8217;t know since which version of the firmware it works that way, but I advise you to upgrade to the latest version (you can also try the upgrade by provisioning, as it does the firmware upgrade too).</p>
<p>My version shows:</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="yaml" style="font-family:monospace;"><span style="color: green;">Boot Version</span><span style="font-weight: bold; color: brown;">: </span>	V1.11<span style="color: green;">
 DSP Version</span><span style="font-weight: bold; color: brown;">: </span>	V3.20<span style="color: green;">
 APP Version</span><span style="font-weight: bold; color: brown;">: </span>	V2.7</pre></td></tr></table></div>

<h2 class="title">Boot workflow</h2>
<p>As detailed in the official documentation, here is its workflow:</p>
<p style="text-align: center;"><a href="http://www.gradstein.info/wp-content/uploads/2010/12/800px-St2030-workflow.png" class="liimagelink"><img class="aligncenter size-full wp-image-413" title="ST2030 boot workflow" src="http://www.gradstein.info/wp-content/uploads/2010/12/800px-St2030-workflow.png" alt="" width="600" height="314" /></a></p>
<h2 class="title">Configuring the DHCP server</h2>
<p>Personnaly I use the default ISC DHCPv3 server (on Ubuntu), but it should work the same way on any implementation (not sure about MS Windows).<br />
As you can see on the workflow, we need to get in the &#8216;Option 43&#8242; state. But to get there, you need to be sure your phone is in a default/factory reset state (otherwise your phone may be setup to boot without DHCP, or not use the HTTP/TFTP data, and get it directly).</p>
<p>In your DHCP server configuration you must be sure you haven&#8217;t defined or played with the 150, 66 or 67 option codes, otherwise you&#8217;ll get into the TFTP boot workflow! If you want to be sure, or to debug your workflow, I recommend you use tcpdump, or even better, tshark. You&#8217;ll get something like that:</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="bash" style="font-family:monospace;">root<span style="color: #000000; font-weight: bold;">@</span>home:<span style="color: #000000; font-weight: bold;">/</span>etc<span style="color: #000000; font-weight: bold;">/</span>dhcp3<span style="color: #666666; font-style: italic;"># tshark host 10.0.8.123</span>
 Capturing on eth0
 <span style="color: #000000;">0.564814</span>     10.0.8.1 -<span style="color: #000000; font-weight: bold;">&gt;</span> 10.0.8.123   DHCP DHCP Offer    - Transaction ID 0xf101e5e6
 <span style="color: #000000;">1.694101</span>     10.0.8.1 -<span style="color: #000000; font-weight: bold;">&gt;</span> 10.0.8.123   DHCP DHCP ACK      - Transaction ID 0xf101e5e6
 <span style="color: #000000;">2.194885</span>     10.0.8.1 -<span style="color: #000000; font-weight: bold;">&gt;</span> 10.0.8.123   ICMP Echo <span style="color: #7a0874; font-weight: bold;">&#40;</span><span style="color: #c20cb9; font-weight: bold;">ping</span><span style="color: #7a0874; font-weight: bold;">&#41;</span> request
 <span style="color: #000000;">2.195531</span>     10.0.8.123 -<span style="color: #000000; font-weight: bold;">&gt;</span> 10.0.8.1   ICMP Echo <span style="color: #7a0874; font-weight: bold;">&#40;</span><span style="color: #c20cb9; font-weight: bold;">ping</span><span style="color: #7a0874; font-weight: bold;">&#41;</span> reply
 <span style="color: #000000;">8.877535</span>     10.0.8.123 -<span style="color: #000000; font-weight: bold;">&gt;</span> 10.0.8.1   TFTP Read Request, File: provisioning<span style="color: #000000; font-weight: bold;">/</span>ST2030<span style="color: #000000; font-weight: bold;">/</span>config<span style="color: #000000; font-weight: bold;">/</span>\000, Transfer type: octet\000
 <span style="color: #000000;">8.882145</span>     10.0.8.1 -<span style="color: #000000; font-weight: bold;">&gt;</span> 10.0.8.123   TFTP Error Code, Code: File not found, Message: File not found\000</pre></td></tr></table></div>

<p>Which is BAD!</p>
<p>So edit your /<strong>etc/dhcp3/dhcpd.conf</strong> configuration file, and *REMOVE* lines like:</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="yaml" style="font-family:monospace;">option option-<span style="">66</span> code <span style="">66</span> = text;
 option option-<span style="">67</span> code <span style="">67</span> = text;</pre></td></tr></table></div>

<p>A correct example would be:</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="yaml" style="font-family:monospace;">option option-<span style="">43</span> code <span style="">43</span> = text;
 option domain-name <span style="color: #CF00CF;">&quot;intra.myhome.fr&quot;</span>;
 option domain-name-servers 10.0.8.3;
&nbsp;
default-lease-time <span style="">12000</span>;
 max-lease-time <span style="">72000</span>;
&nbsp;
authoritative;
 log-facility local7;
&nbsp;
subnet 10.0.8.0 netmask 255.255.255.0 <span class="br0">&#123;</span>
 range 10.0.8.100 10.0.8.150;
 option routers 10.0.8.254;
 option ntp-servers 192.168.100.254;
 <span class="br0">&#125;</span>
 group <span class="br0">&#123;</span>
  option option-<span style="">43</span> <span style="color: #CF00CF;">&quot;&lt;a rel=&quot;</span>nofollow<span style="color: #CF00CF;">&quot; href=&quot;</span>http://10.0.8.165/ST2030.inf<span style="color: #CF00CF;">&quot;&gt;http://10.0.8.165/ST2030.inf&lt;/a&gt;&quot;</span>;
  host test1 <span class="br0">&#123;</span> hardware ethernet 00:1f:9f:<span style="">86</span>:a8:<span style="">29</span>;<span class="br0">&#125;</span>
<span class="br0">&#125;</span></pre></td></tr></table></div>

<p><span style="font-size: 26px; line-height: 28px;">Configuration of the HTTP server and the served files</span></p>
<p>I used NGINX as web server, but it will work equaly well with Apache2 or anything that can serve files throught HTTP.<br />
Just define a root where you will put your firmware and configuration files:</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="yaml" style="font-family:monospace;">server <span class="br0">&#123;</span>
 listen   <span style="">80</span>; <span style="color: blue;">## listen for ipv4</span>
 listen   <span class="br0">&#91;</span>::<span class="br0">&#93;</span>:<span style="">80</span> default ipv6only=on; <span style="color: blue;">## listen for ipv6</span>
 server_name  localhost;
 access_log  /var/log/nginx/provisioning.access.log;
&nbsp;
location / <span class="br0">&#123;</span>
 root   /var/www;
 index  index.html index.htm;
 autoindex on;
 allow 10.0.0.0/<span style="">16</span>;
 <span class="br0">&#125;</span></pre></td></tr></table></div>

<p>After uncompressing the firmware files (from the ZIP), the directory structure in your web root should be the following:</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="yaml" style="font-family:monospace;">root@monserveur:/var/www<span style="color: blue;"># tree</span>
 .
 .-- nginx-default
 .   .-- 50x.html
 .   .-- index.html
 .-- provisioning
 .   .-- ST2030
 .       .-- config
 .       .   .-- ComConf2030SG.R11.1.SED.100804.2.72.2.txt
 .       .   .-- ST2030S_001F9F16A849.txt
 .       .-- data
 .           .-- LangTbl.zz
 .           .-- TelConf2030SG.R11.1.SED.100804.2.72.2.txt
 .           .-- Tone-CW.txt
 .           .-- Tone-Melodies.txt
 .           .-- Tone-RG.txt
 .           .-- ToneTbl.zz
 .           .-- v2030_boot_v111.zz
 .           .-- v2030_dsp_R11.1_SED_v320.zz
 .           .-- v2030SG.R11.1.SED.100804.2.72.2.zz
 .-- ST2030.inf</pre></td></tr></table></div>

<p>The most important file is the <strong>ST2030.inf</strong> file (you can find a default file named &#8216;<strong>ST2030S-ip.inf</strong>&#8216; in the ZIP. The goal of this file is to define where to get all the following files (firmware and configuration files). Mine looks like this:</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="yaml" style="font-family:monospace;"><span class="br0">&#91;</span>application<span class="br0">&#93;</span>
 fwurl=http://10.0.8.165/provisioning/ST2030/data/v2030SG.R11.1.SED.100804.2.72.2.zz
 dspurl=http://10.0.8.165/provisioning/ST2030/data/v2030_dsp_R11.1_SED_v320.zz
 booturl=http://10.0.8.165/provisioning/ST2030/data/v2030_boot_v111.zz
&nbsp;
<span class="br0">&#91;</span>config<span class="br0">&#93;</span>
 telcfg=http://10.0.8.165/provisioning/ST2030/data/TelConf2030SG.R11.1.SED.100804.2.72.2.txt
 common_config=http://10.0.8.165/provisioning/ST2030/config/ComConf2030SG.R11.1.SED.100804.2.72.2.txt
&nbsp;
melodies=http://10.0.8.165/provisioning/ST2030/data/Tone-Melodies.txt
 system_melodies=http://10.0.8.165/provisioning/ST2030/data/Tone-RG.txt
 call_waiting_tone=http://10.0.8.165/provisioning/ST2030/data/Tone-CW.txt
&nbsp;
tone_table=http://10.0.8.165/provisioning/ST2030/data/ToneTbl.zz
 language_table=http://10.0.8.165/provisioning/ST2030/data/LangTbl.zz
&nbsp;
config=http://10.0.8.165/provisioning/ST2030/config/</pre></td></tr></table></div>

<p>All your phone specific files will be looked according to the &#8216;config&#8217; variable. Here, it&#8217;s &#8216;<strong>/provisioning/ST2030/config/</strong>&#8216;, where it will look for <strong>ST2030S_ .txt</strong> (the &#8216;S&#8217; is for SIP).</p>
<p>Before you boot you phone(s), you should at least configure your common file (<strong>ComConf2030SG.R11.1.SED.100804.2.72.2.txt</strong>) to most used values. Then add a file named <strong>ST2030S_ .txt</strong> where you put only the differences with that common file. One of mine&#8217;s looks like:</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="yaml" style="font-family:monospace;"><span class="br0">&#91;</span>ipp<span class="br0">&#93;</span>
 TimeFlag=<span style="">1</span>
 LanguageType=<span style="">1</span>
&nbsp;
<span class="br0">&#91;</span>sip<span class="br0">&#93;</span>
 RegisterServerMP1=10.0.8.165
 ProxyServerMP1=10.0.8.165
 ServiceDomainMP1=10.0.8.165
&nbsp;
RegisterServerBK1=10.0.3.1
 ProxyServerBK1=10.0.3.1
 ServiceDomainBK1=10.0.3.1
&nbsp;
TEL1Number=<span style="">1001</span>
 DisplayName1=Telephone <span style="">1001</span>
 regid1=<span style="">1001</span>
 regpwd1=<span style="">1234</span>
&nbsp;
CallPkupSC=*8X
 AuthMessageServer=10.0.8.165
&nbsp;
<span class="br0">&#91;</span>net<span class="br0">&#93;</span>
 TelnetTime=<span style="">240</span>
 TelnetSrv=<span style="">1</span>
 VLAN=<span style="">0</span>
&nbsp;
<span class="br0">&#91;</span>sys<span class="br0">&#93;</span>
 CodecJitterBufMult=g711a<span class="br0">&#40;</span><span style="">2</span>/<span style="">3</span>/<span style="">7</span><span class="br0">&#41;</span>g711mu<span class="br0">&#40;</span><span style="">1</span>/<span style="">3</span>/<span style="">5</span><span class="br0">&#41;</span>g729<span class="br0">&#40;</span><span style="">2</span>/<span style="">3</span>/<span style="">4</span><span class="br0">&#41;</span>g723<span class="br0">&#40;</span><span style="">1</span>/<span style="">2</span>/<span style="">3</span><span class="br0">&#41;</span>
 CodecPktime=g711a<span class="br0">&#40;</span><span style="">20</span><span class="br0">&#41;</span>g711mu<span class="br0">&#40;</span><span style="">20</span><span class="br0">&#41;</span>g729<span class="br0">&#40;</span><span style="">30</span><span class="br0">&#41;</span>g723<span class="br0">&#40;</span><span style="">30</span><span class="br0">&#41;</span>
 CodecPriority=g711a<span class="br0">&#40;</span><span style="">1</span><span class="br0">&#41;</span>g711mu<span class="br0">&#40;</span><span style="">2</span><span class="br0">&#41;</span>g729<span class="br0">&#40;</span><span style="">3</span><span class="br0">&#41;</span>g723<span class="br0">&#40;</span><span style="">4</span><span class="br0">&#41;</span>
 CodecAdaptivePlayout=g711a<span class="br0">&#40;</span><span style="">1</span><span class="br0">&#41;</span>g711mu<span class="br0">&#40;</span><span style="">1</span><span class="br0">&#41;</span>g729<span class="br0">&#40;</span><span style="">1</span><span class="br0">&#41;</span>g723<span class="br0">&#40;</span><span style="">1</span><span class="br0">&#41;</span>
 Current_Max_Multiline=<span style="">5</span>
 TelnetID=administrator
 TelnetPWD=<span style="">789234</span>
 CountryCode=FR
 config_sn=<span style="">201007300008</span>
 FeatureKeyExt01=L/
 FeatureKeyExt02=L/
 FeatureKeyExt03=L/
 FeatureKeyExt04=L/
 FeatureKeyExt05=L/
 FeatureKeyExt06=L/
 FeatureKeyExt07=L/
 FeatureKeyExt08=S/
 FeatureKeyExt09=S/
 FeatureKeyExt10=S/
 Phonebook1_url=http://myhomeserver.mydomain.fr:<span style="">8000</span>/search?q=<span style="color: blue;">#SEARCH</span>
 Phonebook1_name=My phone book
&nbsp;
<span class="br0">&#91;</span>autoprovision<span class="br0">&#93;</span>
 AutoprovisionFlag=<span style="">1</span>
 AutoprovisionHTTPServer=
 AutoprovisionTFTPServer=
 AutoprovisionTimeDays=<span style="">0</span>
 Autoprovisionstarttime=00:00
 AutoprovisionTimeSpan=<span style="">0</span>
 AutoprovisionRetryPeriod=<span style="">30</span>
 Decryption_Key=Th0mson2$8s8@9z!
&nbsp;
<span class="br0">&#91;</span>ntp<span class="br0">&#93;</span>
 NtpDaylight=<span style="">1</span>
 NTPFlag=<span style="">1</span>
 NtpIP=10.0.1.44
 NtpZoneNum=<span style="">22</span></pre></td></tr></table></div>

<p>This file has NTP and several other parameters adjusted for french infos/timezone. Another note, please take great details when editing this file, as any mistake, will make it be skipped by the phone boot process. Also, don&#8217;t forget to increase/modify the &#8216;config_sn&#8217; attribute (<em><strong>attention, that attribute *MUST* be 12 digits long, i.e. 201007300008</strong></em>).</p>
<h2 class="title">Boot workflow</h2>
<p>To force a firmware update/workflow from scratch, you can click the &#8216;restore default&#8217; button in the phone web interface, or, when the phone starts (unplug/plug the power supply/network cable for PoE), press and hold down the headset and mute buttons.</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="yaml" style="font-family:monospace;">GET /ST2030.inf HTTP/<span style="">1.1</span><span style="color: #CF00CF;">&quot; 200
 GET /provisioning/ST2030/data/v2030SG.R11.1.SED.100804.2.72.2.zz HTTP/1.1 200
 GET /provisioning/ST2030/data/v2030_dsp_R11.1_SED_v320.zz HTTP/1.1 200
 GET /provisioning/ST2030/data/v2030_boot_v111.zz HTTP/1.1 200</span></pre></td></tr></table></div>

<p>Here, it gets the main configuration file, ST2030.inf, and, from it, the APP, DSP and BOOT firmwares.</p>
<p>The phone reboots&#8230;</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="yaml" style="font-family:monospace;">GET /ST2030.inf HTTP/<span style="">1.1</span><span style="color: #CF00CF;">&quot; 200
 GET /provisioning/ST2030/data/Tone-Melodies.txt HTTP/1.1&quot;</span> <span style="">200</span>
 GET /provisioning/ST2030/data/Tone-RG.txt HTTP/<span style="">1.1</span><span style="color: #CF00CF;">&quot; 200
 GET /provisioning/ST2030/data/Tone-CW.txt HTTP/1.1&quot;</span> <span style="">200</span>
 GET /provisioning/ST2030/data/ToneTbl.zz HTTP/<span style="">1.1</span><span style="color: #CF00CF;">&quot; 200
 GET /provisioning/ST2030/data/LangTbl.zz HTTP/1.1&quot;</span> <span style="">200</span>
 GET /provisioning/ST2030/data/TelConf2030SG.R11.1.SED.100804.2.72.2.txt HTTP/<span style="">1.1</span><span style="color: #CF00CF;">&quot; 200
 GET /provisioning/ST2030/config/ComConf2030SG.R11.1.SED.100804.2.72.2.txt HTTP/1.1&quot;</span> <span style="">200</span>
 GET /provisioning/ST2030/config/ST2030S_001F9F16E849.ser HTTP/<span style="">1.1</span><span style="color: #CF00CF;">&quot; 404
 GET /provisioning/ST2030/config/ST2030S_001F9F16E849.txt HTTP/1.1&quot;</span> <span style="">200</span></pre></td></tr></table></div>

<p>Here, it gets the common configuration files for the phone, and looks for a file the the phone&#8217;s MAC address name (ST2030S_001F9F16E849.txt).<br />
The phone reboots&#8230;</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="yaml" style="font-family:monospace;">GET /ST2030.inf HTTP/<span style="">1.1</span><span style="color: #CF00CF;">&quot; 200
 GET /provisioning/ST2030/config/ST2030S_001F9F16E849.ser HTTP/1.1&quot;</span> <span style="">404</span>
 GET /provisioning/ST2030/config/ST2030S_001F9F16E849.txt HTTP/<span style="">1.1</span><span style="color: #CF00CF;">&quot; 200</span></pre></td></tr></table></div>

<p>When there is no modification, you&#8217;ll get the following HTTP request on your server (if you want to force a firmware update/workflow from scratch, you can click the &#8216;restore default&#8217; button in the web interface, or, when the phone boots, press and hold down the headset and mute buttons)</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="yaml" style="font-family:monospace;">GET /ST2030.inf HTTP/<span style="">1.1</span> <span style="">200</span>
 GET /provisioning/ST2030/config/ST2030S_001F9F16E849.ser HTTP/<span style="">1.1</span> <span style="">404</span>
 GET /provisioning/ST2030/config/ST2030S_001F9F16E849.txt HTTP/<span style="">1.1</span> <span style="">200</span></pre></td></tr></table></div>

<p>Here, as you can see with the 404 error code, the ST2030S_001F9F16E849.ser is missing, but that&#8217;s normal. This file only exists if you encrypt your configuration file (tools available in the zip file). So it&#8217;s the same as the .txt file, but encrypted.</p>
<p>So , to summarize the workflow, the phone gets an IP address from the DHCP, and also the url to get the main configuration, throught the option-43 DHCP attribute.</p>
<p>Another way to find out what went wrong, is to look at the APS logs, which are available on the web phone&#8217;s GUI, in the &#8216;setup&#8217; menu, option &#8216;APS Log&#8217;:</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="yaml" style="font-family:monospace;">Autoprovision Process start
 Begin General file download<span style="color: cyan;">...</span><span style="color: green;">
 General file</span><span style="font-weight: bold; color: brown;">: </span>ST2030.inf download successfully!
 Begin Firmware download<span style="color: cyan;">...</span>
 Firmware filename is the same!
 Begin DSP download<span style="color: cyan;">...</span>
 DSP filename is the same!
 Begin Boot Code download<span style="color: cyan;">...</span>
 BOOT code filename is the same!
 Begin Melody download<span style="color: cyan;">...</span>
 Begin Common Config download<span style="color: cyan;">...</span>
 Common Config filename is the same!
 Begin Mac config download<span style="color: cyan;">...</span><span style="color: green;">
 Error</span><span style="font-weight: bold; color: brown;">: </span>provisioning/ST2030/config/ST2030S_001F9F16E849.ser file not found!
 Now will try to search txt file!<span style="color: green;">
 MacConfig</span><span style="font-weight: bold; color: brown;">: </span>provisioning/ST2030/config/ST2030S_001F9F16E849.txt download successfully!
 Serial number is not the same!
 Begin upgrading config file<span style="color: cyan;">...</span>
 Check config file syntax
 Check config file syntax successfully!
 Upgrading config file successfully!
 Reboot<span style="color: cyan;">...</span>..
 <span class="br0">&#91;</span><span style="color: cyan;">...</span><span class="br0">&#93;</span>
 Begin General file download<span style="color: cyan;">...</span><span style="color: green;">
 General file</span><span style="font-weight: bold; color: brown;">: </span>ST2030.inf download successfully!
 Begin Firmware download<span style="color: cyan;">...</span>
 Firmware filename is the same!
 Begin DSP download<span style="color: cyan;">...</span>
 Begin Telephone Config download<span style="color: cyan;">...</span>
 Telephone config filename is the same!
 Begin Common Config download<span style="color: cyan;">...</span>
 Common Config filename is the same!
 Begin Mac config download<span style="color: cyan;">...</span><span style="color: green;">
 Error</span><span style="font-weight: bold; color: brown;">: </span>provisioning/ST2030/config/ST2030S_001F9F16E849.ser file not found!
 Now will try to search txt file!<span style="color: green;">
 MacConfig</span><span style="font-weight: bold; color: brown;">: </span>provisioning/ST2030/config/ST2030S_001F9F16E849.txt download successfully!
 Serial number is the same!
 Begin upgrading config file<span style="color: cyan;">...</span>
 <span style="font-weight: bold;">No</span> upgrading config file required<span style="color: cyan;">...</span>
 Autoprovision Process End</pre></td></tr></table></div>

<p><strong><span style="text-decoration: underline;">Update:</span></strong> One last note, when you edit/update your MAC named file, do not forget to update/increment the config_sn file, otherwise the phone will think the data hasn&#8217;t changed!</p>
<p>Now, to finish, you just have to create a new file (named with a MAC address) for each of your phones. In the next article, I&#8217;ll show you how to make Asterisk do it for you, all automatically, from sip.conf&#8217;s files!</p>
<div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/LiorGradsteinsBlog?a=SZtsjdgSJOs:CZvEsnIVRqY:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/LiorGradsteinsBlog?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/LiorGradsteinsBlog?a=SZtsjdgSJOs:CZvEsnIVRqY:V_sGLiPBpWU"><img src="http://feeds.feedburner.com/~ff/LiorGradsteinsBlog?i=SZtsjdgSJOs:CZvEsnIVRqY:V_sGLiPBpWU" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/LiorGradsteinsBlog/~4/SZtsjdgSJOs" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://www.banquise.org/software/asterisk/auto-provisioning-asterisk-st2030-technicolorthomson-phones/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://www.banquise.org/software/asterisk/auto-provisioning-asterisk-st2030-technicolorthomson-phones/</feedburner:origLink></item>
		<item>
		<title>How to make the simplest unittests in Python</title>
		<link>http://feedproxy.google.com/~r/LiorGradsteinsBlog/~3/mAJ5_5b6d14/</link>
		<comments>http://www.banquise.org/python/simplest-unittests-python/#comments</comments>
		<pubDate>Wed, 15 Sep 2010 12:21:43 +0000</pubDate>
		<dc:creator>Lior Gradstein</dc:creator>
				<category><![CDATA[python]]></category>
		<category><![CDATA[ruby]]></category>
		<category><![CDATA[code]]></category>
		<category><![CDATA[Development Tools]]></category>
		<category><![CDATA[programming]]></category>
		<category><![CDATA[python projects]]></category>
		<category><![CDATA[tests]]></category>
		<category><![CDATA[unittests]]></category>

		<guid isPermaLink="false">http://www.gradstein.info/?p=405</guid>
		<description><![CDATA[Testing your code is nearly a requirement (even more so in Ruby). Unittests are now the most vital elements for evaluating the quality/viability of a project. I was a little jealous of Ruby where you don&#8217;t have so much to write to implement unittests. Here is a simple example: 1 2 3 4 5 6 [...]]]></description>
				<content:encoded><![CDATA[<p>Testing your code is nearly a requirement (even more so in Ruby). Unittests are now the most vital elements for evaluating the quality/viability of a project.<br />
I was a little jealous of Ruby where you don&#8217;t have so much to write to implement unittests. Here is a simple example:</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
</pre></td><td class="code"><pre class="ruby" style="font-family:monospace;"><span style="color:#CC0066; font-weight:bold;">require</span> <span style="color:#996600;">&quot;mymodule&quot;</span>
<span style="color:#CC0066; font-weight:bold;">require</span> <span style="color:#996600;">&quot;test/unit&quot;</span>
&nbsp;
<span style="color:#9966CC; font-weight:bold;">class</span> TestMyModule <span style="color:#006600; font-weight:bold;">&amp;</span>lt; <span style="color:#CC00FF; font-weight:bold;"><span style="color:#6666ff; font-weight:bold;">Test::Unit::TestCase</span></span>
&nbsp;
  <span style="color:#9966CC; font-weight:bold;">def</span> test_simple
     assert_equal<span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#006666;">1</span>, <span style="color:#006666;">1</span> <span style="color:#006600; font-weight:bold;">&#41;</span>
  <span style="color:#9966CC; font-weight:bold;">end</span>
<span style="color:#9966CC; font-weight:bold;">end</span></pre></td></tr></table></div>

<p>Now, using <a href="http://somethingaboutorange.com/mrl/projects/nose" class="liexternal">Nose</a>, you can get even shorter code. If you do standard Python projects, you&#8217;ll use a setup.py file. To use nose, you do not even need to specify the path where to find the tests, just add two lines (tests_require and test_suite) to call nosetest:</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
</pre></td><td class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">from</span> setuptools <span style="color: #ff7700;font-weight:bold;">import</span> setup<span style="color: #66cc66;">,</span> find_packages
<span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">sys</span><span style="color: #66cc66;">,</span> <span style="color: #dc143c;">os</span>
<span style="color: #ff7700;font-weight:bold;">import</span> mymodule
&nbsp;
version <span style="color: #66cc66;">=</span> mymodule.__version__
&nbsp;
setup<span style="color: black;">&#40;</span>name<span style="color: #66cc66;">=</span><span style="color: #483d8b;">'myproject'</span><span style="color: #66cc66;">,</span>
      version<span style="color: #66cc66;">=</span>version<span style="color: #66cc66;">,</span>
      description<span style="color: #66cc66;">=</span><span style="color: #483d8b;">&quot;Module to display blah blah blah.&quot;</span><span style="color: #66cc66;">,</span>
      long_description<span style="color: #66cc66;">=</span><span style="color: #483d8b;">&quot;&quot;&quot; &quot;&quot;&quot;</span><span style="color: #66cc66;">,</span>
      classifiers<span style="color: #66cc66;">=</span><span style="color: black;">&#91;</span><span style="color: black;">&#93;</span><span style="color: #66cc66;">,</span> <span style="color: #808080; font-style: italic;"># Get strings from http://pypi.python.org/pypi?%3Aaction=list_classifiers</span>
      keywords<span style="color: #66cc66;">=</span><span style="color: #483d8b;">'mymodule foobar'</span><span style="color: #66cc66;">,</span>
      author<span style="color: #66cc66;">=</span><span style="color: #483d8b;">'Luc Stepniewski'</span><span style="color: #66cc66;">,</span>
      author_email<span style="color: #66cc66;">=</span><span style="color: #483d8b;">'<span class="mh-email">l<a href='http://www.google.com/recaptcha/mailhide/d?k=01WFuVUzSgCx86g3T-2PkL0g==&amp;c=gEgn2-_qa2iYC4hm0g23sTwhCFo58xX2DouAAVPPrqo=' onclick="window.open('http://www.google.com/recaptcha/mailhide/d?k=01WFuVUzSgCx86g3T-2PkL0g==&amp;c=gEgn2-_qa2iYC4hm0g23sTwhCFo58xX2DouAAVPPrqo=', '', 'toolbar=0,scrollbars=0,location=0,statusbar=0,menubar=0,resizable=0,width=500,height=300'); return false;" title="Reveal this e-mail address">...</a>@gradstein.info</span>'</span><span style="color: #66cc66;">,</span>
      url<span style="color: #66cc66;">=</span><span style="color: #483d8b;">''</span><span style="color: #66cc66;">,</span>
      license<span style="color: #66cc66;">=</span><span style="color: #483d8b;">'GPL'</span><span style="color: #66cc66;">,</span>
      packages<span style="color: #66cc66;">=</span>find_packages<span style="color: black;">&#40;</span>exclude<span style="color: #66cc66;">=</span><span style="color: black;">&#91;</span><span style="color: #483d8b;">'ez_setup'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'examples'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'tests'</span><span style="color: black;">&#93;</span><span style="color: black;">&#41;</span><span style="color: #66cc66;">,</span>
      include_package_data<span style="color: #66cc66;">=</span><span style="color: #008000;">True</span><span style="color: #66cc66;">,</span>
      tests_require<span style="color: #66cc66;">=</span><span style="color: #483d8b;">'nose'</span><span style="color: #66cc66;">,</span>
      test_suite<span style="color: #66cc66;">=</span><span style="color: #483d8b;">'nose.collector'</span><span style="color: #66cc66;">,</span>
      zip_safe<span style="color: #66cc66;">=</span><span style="color: #008000;">False</span><span style="color: #66cc66;">,</span>
      install_requires<span style="color: #66cc66;">=</span><span style="color: black;">&#91;</span>
          <span style="color: #808080; font-style: italic;"># -*- Extra requirements: -*-</span>
          <span style="color: #483d8b;">'simplejson'</span><span style="color: #66cc66;">,</span>
      <span style="color: black;">&#93;</span><span style="color: #66cc66;">,</span>
      entry_points<span style="color: #66cc66;">=</span><span style="color: #483d8b;">&quot;&quot;&quot;
      # -*- Entry points: -*-
      [console_scripts]
      mymodule = mymodule.mainmodule:main
      &quot;&quot;&quot;</span><span style="color: #66cc66;">,</span>
      <span style="color: black;">&#41;</span></pre></td></tr></table></div>

<p>Now, to add tests, you just have to create a directory named tests (in the root of your project, where your setup.py resides, and then add a python file()s. No need to add a __init__.py to set the directory as a module. Now just add simple python files, like my-tests.py :</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
</pre></td><td class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">import</span> mymodule
&nbsp;
<span style="color: #ff7700;font-weight:bold;">class</span> TestAstInfoCli<span style="color: black;">&#40;</span><span style="color: #008000;">object</span><span style="color: black;">&#41;</span>:
    <span style="color: #ff7700;font-weight:bold;">def</span> setup<span style="color: black;">&#40;</span><span style="color: #008000;">self</span><span style="color: black;">&#41;</span>:
        <span style="color: #ff7700;font-weight:bold;">pass</span>
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">def</span> teardown<span style="color: black;">&#40;</span><span style="color: #008000;">self</span><span style="color: black;">&#41;</span>:
        <span style="color: #ff7700;font-weight:bold;">pass</span>
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">def</span> test_annuaire_inverse<span style="color: black;">&#40;</span><span style="color: #008000;">self</span><span style="color: black;">&#41;</span>:
        <span style="color: #ff7700;font-weight:bold;">assert</span> <span style="color: #ff4500;">1</span> <span style="color: #66cc66;">==</span> <span style="color: #ff4500;">1</span></pre></td></tr></table></div>

<p>As you can see, no need to import anything for doing unittests, not even the standard python unittest module! That&#8217;s better than ruby! The downside of this is that nose is an &#8216;external&#8217; package, so you&#8217;ll have to install it first (or set it as a dependency in your setup.py file, as shown above).</p>
<p>If you don&#8217;t use a setup.py, you can call nose directly from the command line, with &#8216;nosetest&#8217;.</p>
<p>Now, let&#8217;s find an equivalent to the really cool rspec ruby module!</p>
<div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/LiorGradsteinsBlog?a=mAJ5_5b6d14:ynsANeq4-SI:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/LiorGradsteinsBlog?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/LiorGradsteinsBlog?a=mAJ5_5b6d14:ynsANeq4-SI:V_sGLiPBpWU"><img src="http://feeds.feedburner.com/~ff/LiorGradsteinsBlog?i=mAJ5_5b6d14:ynsANeq4-SI:V_sGLiPBpWU" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/LiorGradsteinsBlog/~4/mAJ5_5b6d14" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://www.banquise.org/python/simplest-unittests-python/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://www.banquise.org/python/simplest-unittests-python/</feedburner:origLink></item>
		<item>
		<title>Default behaviour in implementation of STOMP protocol in RabbitMQ with python</title>
		<link>http://feedproxy.google.com/~r/LiorGradsteinsBlog/~3/8w7zHDfmqeY/</link>
		<comments>http://www.banquise.org/python/default-behaviour-implementation-stomp-protocol-rabbitmq-python/#comments</comments>
		<pubDate>Fri, 27 Aug 2010 15:51:39 +0000</pubDate>
		<dc:creator>Lior Gradstein</dc:creator>
				<category><![CDATA[network]]></category>
		<category><![CDATA[python]]></category>
		<category><![CDATA[rabbitmq]]></category>
		<category><![CDATA[Advanced Message Queuing Protocol]]></category>
		<category><![CDATA[amqp]]></category>
		<category><![CDATA[consumers]]></category>
		<category><![CDATA[direct]]></category>
		<category><![CDATA[example]]></category>
		<category><![CDATA[Internet protocols]]></category>
		<category><![CDATA[one]]></category>
		<category><![CDATA[protocol]]></category>
		<category><![CDATA[round-robin]]></category>
		<category><![CDATA[stomp]]></category>
		<category><![CDATA[stompy]]></category>

		<guid isPermaLink="false">http://www.gradstein.info/?p=368</guid>
		<description><![CDATA[Why STOMP? Why STOMP, and not directly AMQP, as I&#8217;m using RabbitMQ. No real reason, but the fact that there are less dependencies on a STOMP client, as it&#8217;s just a socket with text sent. Implementations There are several implementations of the STOMP protocol for Python. The module I chose is python-stomp (version 0.2.9), from [...]]]></description>
				<content:encoded><![CDATA[<h2>Why STOMP?</h2>
<p>Why STOMP, and not directly AMQP, as I&#8217;m using RabbitMQ. No real reason, but the fact that there are less dependencies on a STOMP client, as it&#8217;s just a socket with text sent.</p>
<h2>Implementations</h2>
<p>There are <a href="http://pypi.python.org/pypi?%3Aaction=search&#038;term=stomp&#038;submit=search" class="liexternal">several implementations</a> of the STOMP protocol for Python. The module I chose is <a href="http://pypi.python.org/pypi/stompy/" class="liexternal">python-stomp</a> (version 0.2.9), from Benjamin W. Smith. It&#8217;s simple and easy to understand.</p>
<h2>Simple Code Examples</h2>
<p>sto_send.py:</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
</pre></td><td class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">from</span> stompy.<span style="color: black;">simple</span> <span style="color: #ff7700;font-weight:bold;">import</span> Client
&nbsp;
stomp <span style="color: #66cc66;">=</span> Client<span style="color: black;">&#40;</span>host<span style="color: #66cc66;">=</span><span style="color: #483d8b;">'rabbitmq2'</span><span style="color: black;">&#41;</span>
stomp.<span style="color: black;">connect</span><span style="color: black;">&#40;</span>username<span style="color: #66cc66;">=</span><span style="color: #483d8b;">'guest'</span><span style="color: #66cc66;">,</span>password<span style="color: #66cc66;">=</span><span style="color: #483d8b;">'noneofyourbusiness'</span><span style="color: black;">&#41;</span>
stomp.<span style="color: black;">put</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'Thomas est une b*te à Tetris...'</span><span style="color: #66cc66;">,</span> destination<span style="color: #66cc66;">=</span><span style="color: #483d8b;">'/queue/jeuvideo'</span><span style="color: black;">&#41;</span>
stomp.<span style="color: black;">disconnect</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span></pre></td></tr></table></div>

<p>sto_receive.py:</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
</pre></td><td class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">from</span> stompy.<span style="color: black;">simple</span> <span style="color: #ff7700;font-weight:bold;">import</span> Client
&nbsp;
stomp <span style="color: #66cc66;">=</span> Client<span style="color: black;">&#40;</span>host<span style="color: #66cc66;">=</span><span style="color: #483d8b;">'rabbitmq2'</span><span style="color: black;">&#41;</span>
stomp.<span style="color: black;">connect</span><span style="color: black;">&#40;</span>username<span style="color: #66cc66;">=</span><span style="color: #483d8b;">'guest'</span><span style="color: #66cc66;">,</span>password<span style="color: #66cc66;">=</span><span style="color: #483d8b;">'noneofyourbusiness'</span><span style="color: black;">&#41;</span>
stomp.<span style="color: black;">subscribe</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'/queue/jeuvideo'</span><span style="color: black;">&#41;</span>
message <span style="color: #66cc66;">=</span> stomp.<span style="color: black;">get</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">print</span> message.<span style="color: black;">body</span>
&nbsp;
<span style="color: #808080; font-style: italic;">#stomp.ack(message)</span>
stomp.<span style="color: black;">unsubscribe</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'/queue/video'</span><span style="color: black;">&#41;</span>
stomp.<span style="color: black;">disconnect</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span></pre></td></tr></table></div>

<p>Everything is working fine, when launching sto_receive.py, I receive the message. But when I launched several receivers, I noticed, that ONLY ONE programs received the message! After some research, I found the answer: As documented <a href="https://dev.rabbitmq.com/wiki/StompGateway" class="liexternal">in the RabbitMQ wiki</a>, the default exchange is &#8216;direct&#8217;:</p>
<blockquote><p>[...]when messages leave a queue for a consumer, they are not duplicated. One message, sitting on a queue, is delivered to only one of the available consumers. [...] If there are multiple clients, all SUBSCRIBEing to the same queue, then there will be multiple consumers all on the same queue, leading to round-robin delivery to those clients.</p></blockquote>
<p>There is <a href="https://dev.rabbitmq.com/wiki/StompGateway" class="liexternal">an explanation</a> on how to change the behaviour, by changing the exchange type, and some of particular bits (like the id). I even found <a href="http://github.com/dcarley/mcollective-plugins/commit/4801dda81cdb7fca2fc3f87efdcc3295d497e973" class="liexternal">an example of modification</a> for use in the equivalent <a href="http://rubygems.org/gems/stomp" class="liexternal">STOMP Ruby module</a>.</p>
<p>Here are the modifications. The good news is that there is no need to patch the stompy module, as the author provided the possibility to pass arbitrary parameters to the headers by the use of the &#8216;conf&#8217; variable. </p>
<p>The important points are:</p>
<ul>
<li>You need to define an exchange of type amq.topic</li>
<li>You need to set an id, which is different for each client</li>
<li>As you&#8217;re using topics, you&#8217;ll have to specify a routing_key</li>
</ul>
<p>sto_receive.py:</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
</pre></td><td class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">from</span> stompy.<span style="color: black;">simple</span> <span style="color: #ff7700;font-weight:bold;">import</span> Client
<span style="color: #ff7700;font-weight:bold;">import</span> uuid
&nbsp;
unique_id <span style="color: #66cc66;">=</span> uuid.<span style="color: black;">uuid4</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
&nbsp;
stomp <span style="color: #66cc66;">=</span> Client<span style="color: black;">&#40;</span>host<span style="color: #66cc66;">=</span><span style="color: #483d8b;">'rabbitmq2'</span><span style="color: black;">&#41;</span>
stomp.<span style="color: black;">connect</span><span style="color: black;">&#40;</span>username<span style="color: #66cc66;">=</span><span style="color: #483d8b;">'guest'</span><span style="color: #66cc66;">,</span>password<span style="color: #66cc66;">=</span><span style="color: #483d8b;">'nonononono'</span><span style="color: black;">&#41;</span>
&nbsp;
stomp.<span style="color: black;">subscribe</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">''</span><span style="color: #66cc66;">,</span>
                conf<span style="color: #66cc66;">=</span><span style="color: black;">&#123;</span><span style="color: #483d8b;">'exchange'</span>: <span style="color: #483d8b;">'amq.topic'</span><span style="color: #66cc66;">,</span>
                      <span style="color: #483d8b;">'routing_key'</span>:<span style="color: #483d8b;">'x.#'</span><span style="color: #66cc66;">,</span>
                      <span style="color: #483d8b;">'id'</span>: unique_id<span style="color: #66cc66;">,</span>
                      <span style="color: black;">&#125;</span><span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #808080; font-style: italic;"># Wait for a message to appear</span>
<span style="color: #ff7700;font-weight:bold;">while</span> <span style="color: #ff4500;">1</span>:
    message <span style="color: #66cc66;">=</span> stomp.<span style="color: black;">get</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
    <span style="color: #ff7700;font-weight:bold;">print</span> message.<span style="color: black;">body</span>
&nbsp;
<span style="color: #808080; font-style: italic;">#stomp.ack(message)</span>
stomp.<span style="color: black;">unsubscribe</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">''</span><span style="color: #66cc66;">,</span>conf<span style="color: #66cc66;">=</span><span style="color: black;">&#123;</span><span style="color: #483d8b;">'id'</span>: unique_id<span style="color: black;">&#125;</span><span style="color: black;">&#41;</span>
stomp.<span style="color: black;">disconnect</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span></pre></td></tr></table></div>

<p>sto_send.py:</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
</pre></td><td class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">from</span> stompy.<span style="color: black;">simple</span> <span style="color: #ff7700;font-weight:bold;">import</span> Client
&nbsp;
&nbsp;
&nbsp;
stomp <span style="color: #66cc66;">=</span> Client<span style="color: black;">&#40;</span>host<span style="color: #66cc66;">=</span><span style="color: #483d8b;">'rabbitmq2'</span><span style="color: black;">&#41;</span>
stomp.<span style="color: black;">connect</span><span style="color: black;">&#40;</span>username<span style="color: #66cc66;">=</span><span style="color: #483d8b;">'guest'</span><span style="color: #66cc66;">,</span>password<span style="color: #66cc66;">=</span><span style="color: #483d8b;">'nonononono'</span><span style="color: black;">&#41;</span>
&nbsp;
&nbsp;
<span style="color: #ff7700;font-weight:bold;">for</span> i <span style="color: #ff7700;font-weight:bold;">in</span> <span style="color: #008000;">range</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">10000</span><span style="color: black;">&#41;</span>:
 stomp.<span style="color: black;">put</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'Thomas est une b*te au Tetris...'</span><span style="color: #66cc66;">,</span> destination<span style="color: #66cc66;">=</span><span style="color: #483d8b;">'x.y'</span><span style="color: #66cc66;">,</span>
          conf<span style="color: #66cc66;">=</span><span style="color: black;">&#123;</span><span style="color: #483d8b;">'exchange'</span>:<span style="color: #483d8b;">'amq.topic'</span><span style="color: #66cc66;">,</span>
                <span style="color: #808080; font-style: italic;">#  'routing_key':'x.y'</span>
                <span style="color: black;">&#125;</span><span style="color: black;">&#41;</span>
&nbsp;
stomp.<span style="color: black;">disconnect</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span></pre></td></tr></table></div>

<div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/LiorGradsteinsBlog?a=8w7zHDfmqeY:yUKyDDZ4ct0:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/LiorGradsteinsBlog?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/LiorGradsteinsBlog?a=8w7zHDfmqeY:yUKyDDZ4ct0:V_sGLiPBpWU"><img src="http://feeds.feedburner.com/~ff/LiorGradsteinsBlog?i=8w7zHDfmqeY:yUKyDDZ4ct0:V_sGLiPBpWU" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/LiorGradsteinsBlog/~4/8w7zHDfmqeY" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://www.banquise.org/python/default-behaviour-implementation-stomp-protocol-rabbitmq-python/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		<feedburner:origLink>http://www.banquise.org/python/default-behaviour-implementation-stomp-protocol-rabbitmq-python/</feedburner:origLink></item>
		<item>
		<title>Puppet: Files found in modules without specifying ‘modules’ in file path will be deprecated in the next major release</title>
		<link>http://feedproxy.google.com/~r/LiorGradsteinsBlog/~3/OmWmc1HUqY4/</link>
		<comments>http://www.banquise.org/network/puppet-files-modules-modules-file-path-deprecated-major-release/#comments</comments>
		<pubDate>Thu, 19 Aug 2010 14:11:00 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[network]]></category>
		<category><![CDATA[puppet]]></category>
		<category><![CDATA[ruby]]></category>
		<category><![CDATA[deprecation]]></category>
		<category><![CDATA[notice]]></category>
		<category><![CDATA[warning]]></category>

		<guid isPermaLink="false">http://www.gradstein.info/?p=351</guid>
		<description><![CDATA[DEPRECATION NOTICE: Files found in modules without specifying &#8216;modules&#8217; in file path will be deprecated in the next major release. If you get this warning in your puppet logs, you should take action (only if you don&#8217;t have any Puppet agent with a version]]></description>
				<content:encoded><![CDATA[<blockquote><p>DEPRECATION NOTICE: Files found in modules without specifying &#8216;modules&#8217; in file path will be deprecated in the next major release.
</p></blockquote>
<p>If you get this warning in your puppet logs, you should take action (only if you don&#8217;t have any Puppet agent with a version <= 0.24) and modify all you references to file resources.<br />
For example, if you have a module named 'ssh', normally, up to puppet 0.25 you would reference a file to it as:</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="ruby" style="font-family:monospace;">source <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#996600;">&quot;puppet:///ssh/authorized_keys&quot;</span>,<span style="color:#006600; font-weight:bold;">&#93;</span></pre></td></tr></table></div>

<p>But now, you need to insert a &#8216;module&#8217; identifier in between like this:</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="ruby" style="font-family:monospace;">source <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#996600;">&quot;puppet:///modules/ssh/authorized_keys&quot;</span>,<span style="color:#006600; font-weight:bold;">&#93;</span></pre></td></tr></table></div>

<p><em>Just a small note: It seems that the templates do not need any modification.</em></p>
<div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/LiorGradsteinsBlog?a=OmWmc1HUqY4:5cebwCg-l3k:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/LiorGradsteinsBlog?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/LiorGradsteinsBlog?a=OmWmc1HUqY4:5cebwCg-l3k:V_sGLiPBpWU"><img src="http://feeds.feedburner.com/~ff/LiorGradsteinsBlog?i=OmWmc1HUqY4:5cebwCg-l3k:V_sGLiPBpWU" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/LiorGradsteinsBlog/~4/OmWmc1HUqY4" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://www.banquise.org/network/puppet-files-modules-modules-file-path-deprecated-major-release/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://www.banquise.org/network/puppet-files-modules-modules-file-path-deprecated-major-release/</feedburner:origLink></item>
		<item>
		<title>Where do I find pngout for Linux?</title>
		<link>http://feedproxy.google.com/~r/LiorGradsteinsBlog/~3/F2hft9Z2AJY/</link>
		<comments>http://www.banquise.org/software/where-do-i-find-pngout-for-linux/#comments</comments>
		<pubDate>Tue, 05 Jan 2010 17:11:21 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[software]]></category>

		<guid isPermaLink="false">http://www.gradstein.info/?p=290</guid>
		<description><![CDATA[I just found a nice comparison chart of different compression programs for PNG images (optimizations). It seems that PNGout is the best of the best :-) On the author&#8217;s website, there&#8217;s only a windows version. The link to the Linux version gets redirected to a gtagaming website?! After asking the great oracle Google where I [...]]]></description>
				<content:encoded><![CDATA[<p>I just found a <a href="http://www.olegkikin.com/png_optimizers/" class="liexternal">nice comparison chart of different compression programs</a> for PNG images (optimizations). It seems that PNGout is the best of the best :-) On the author&#8217;s website, there&#8217;s only a windows version. The link to the Linux version gets redirected to a gtagaming website?!<br />
After asking the great oracle Google where I could find a version for Linux, he replied to me I could find it on <a href="http://www.jonof.id.au/pngout" class="liexternal">JonoF&#8217;s website</a>.</p>
<div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/LiorGradsteinsBlog?a=F2hft9Z2AJY:uFj3Ksuh6kk:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/LiorGradsteinsBlog?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/LiorGradsteinsBlog?a=F2hft9Z2AJY:uFj3Ksuh6kk:V_sGLiPBpWU"><img src="http://feeds.feedburner.com/~ff/LiorGradsteinsBlog?i=F2hft9Z2AJY:uFj3Ksuh6kk:V_sGLiPBpWU" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/LiorGradsteinsBlog/~4/F2hft9Z2AJY" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://www.banquise.org/software/where-do-i-find-pngout-for-linux/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://www.banquise.org/software/where-do-i-find-pngout-for-linux/</feedburner:origLink></item>
	</channel>
</rss><!-- Performance optimized by W3 Total Cache. Learn more: http://www.w3-edge.com/wordpress-plugins/

Page Caching using memcached

 Served from: www.banquise.org @ 2013-05-16 19:48:58 by W3 Total Cache -->
