<?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:feedburner="http://rssnamespace.org/feedburner/ext/1.0" version="2.0"><channel><title>vedovini.net</title> <link>http://vedovini.net</link> <description>Founded in 1969, building software since 1985.</description> <lastBuildDate>Thu, 03 Nov 2011 18:27:54 +0000</lastBuildDate> <language>en</language> <sy:updatePeriod>hourly</sy:updatePeriod> <sy:updateFrequency>1</sy:updateFrequency> <atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/rss+xml" href="http://feeds.feedburner.com/cvedovini/blog" /><feedburner:info uri="cvedovini/blog" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><feedburner:emailServiceId>cvedovini/blog</feedburner:emailServiceId><feedburner:feedburnerHostname>http://feedburner.google.com</feedburner:feedburnerHostname><item><title>The network of trust</title><link>http://feedproxy.google.com/~r/cvedovini/blog/~3/YYhjl8lltoQ/</link> <comments>http://vedovini.net/2011/10/the-network-of-trust/#comments</comments> <pubDate>Thu, 06 Oct 2011 15:33:46 +0000</pubDate> <dc:creator>Claude</dc:creator> <category><![CDATA[freelancing]]></category> <category><![CDATA[networking]]></category> <category><![CDATA[freelance]]></category> <category><![CDATA[network]]></category> <category><![CDATA[reputation]]></category> <category><![CDATA[switzerland]]></category> <category><![CDATA[trust]]></category><guid isPermaLink="false">http://vedovini.net/?p=720</guid> <description><![CDATA[One of the questions I am often asked when I meet fellow freelance developers is how do I find work? The answer is really simple: I don't, work finds me!]]></description> <content:encoded><![CDATA[<p><strong><a href="http://vedovini.net/2011/10/the-network-of-trust/3491975150_970196c001_z/" rel="attachment wp-att-727"><img class="alignright size-medium wp-image-727" title="3491975150_970196c001_z" src="http://static.vedovini.net/blog/wp-content/uploads/2011/10/3491975150_970196c001_z-225x300.jpg" alt="" width="225" height="300" /></a>One of the questions I am often asked when I meet fellow freelance developers is how do I find work? The answer is really simple: I don&#8217;t, work finds me!</strong></p><p>This may just apply to Switzerland, the Geneva area, software development or me but I doubt it. I think it applies to any kind of freelance job, anywhere. And I also think this is hardly a secret :)</p><p>In order to have work find you, you need only one thing: a network of trust.</p><p>You need people you trust and who trust you. The trust factor here is important because you don&#8217;t need poisonous clients from hell, you need the best clients, those with the best projects and who actually pay the bills in time. And for a network to give you that there must be a safe and natural path leading the client to you.</p><h3>Building a network</h3><p>Building a network is not a matter of minutes and distributing name cards is only the beginning. It is about building relationships with people. Building trust among your network will be the subject of the next chapter, for now let&#8217;s see where you can find people to build your network.</p><p>First, you certainly already have a network. If you worked in the corporate world before being a freelancer it is composed of your former colleagues and bosses but also the people you were in school with. Some of them might become clients or referrals. Then you will need new friends, and the most important thing to make new friends is to meet new people. If you are the shy type then get over it or get back to corporate world.</p><p>To meet new people you need to find gatherings. Ask around you, use Google and social networks and find groups of professionals that gather regularly. Conferences are also good but you need to be able to follow up on the people you meet (you hardly build a trust relationship when you meet people once in a year). You can even build your own group if you are, say a Google AppEngine specialist but there is no local GAE users group. This is important: you need to meet people around topics that interest you! If you go to a RoR meetup thinking &#8220;I don&#8217;t care about RoR but if those guys have a Java project coming in they may refer me&#8221; then you are doing it wrong. Even if &#8220;those guys&#8221; get a Java project and cannot convince the client to switch to RoR, they won&#8217;t think about you because you were enable to connect with them during the meetup.</p><p>I will not discuss how to connect with people, there is no secret handshake and if you have relational issues may be you should consider working this first.</p><p>And then you will have to add your clients to your network. They are an important part of it because they have a unique point of view, they trusted you with their projects and they hopefully are more than happy with your work.</p><p>Another thing is that you will need your network to think about you. When the time comes, your name must be floating at the surface of their brain. With the advent of social networks this is something that has become relatively easy, so do not hesitate to use Facebook, Twitter et al. in addition to regular face to face meetings. Your network must hear about you, it must see your face and it must remember who you are. Obviously you need to stay relevant, you can share your passions and your wisdom but you also need to share useful professional information.</p><p><span class="Apple-style-span" style="font-size: 15px; font-weight: bold;">Building trust</span></p><p>This is the most difficult part, you must be recognised by your peers and be a point of reference for your clients. I only found one effective way to build trust (if there are others I will be happy to read about them in the comments) and this is to overdeliver.</p><p>For clients, overdelivering means exceeding their expectations. It can be in term of schedule, functionalities, quality or just being there when they need you. Or before they need you.</p><p>For fellow freelancers or colleagues it means sharing work and knowledge, helping them when they need help, without demanding or expecting anything in return. This can be done is several ways, participating in open source projects is one, giving presentations at meetups or speeches at conference are others.</p><p>If you think a project or client may be dubious do not refer it to someone else without the proper warnings. Likewise, do not send a trusting client to an unknown resource without the proper disclaimer. Never refer a client you would not take or a freelancer you would not hire.</p><p>Once enough people in your network trust you the network effect will kick in, some people will trust you just because others do and you will receive e-mails from people you don&#8217;t know who want to work with you.</p><p>And you? How do you find work?</p><h3  class="related_post_title">Related posts: (automatically generated)</h3><ul class="related_post"><li><a href="http://vedovini.net/2008/05/going-solo-is-over/" title="Going-Solo is over">Going-Solo is over</a></li><li><a href="http://vedovini.net/2007/04/cest-ca-la-suisse/" title="C&#8217;est ça la Suisse">C&#8217;est ça la Suisse</a></li></ul><div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/cvedovini/blog?a=YYhjl8lltoQ:ikXTLRQZWmQ:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/cvedovini/blog?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/cvedovini/blog?a=YYhjl8lltoQ:ikXTLRQZWmQ:F7zBnMyn0Lo"><img src="http://feeds.feedburner.com/~ff/cvedovini/blog?i=YYhjl8lltoQ:ikXTLRQZWmQ:F7zBnMyn0Lo" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/cvedovini/blog?a=YYhjl8lltoQ:ikXTLRQZWmQ:V_sGLiPBpWU"><img src="http://feeds.feedburner.com/~ff/cvedovini/blog?i=YYhjl8lltoQ:ikXTLRQZWmQ:V_sGLiPBpWU" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/cvedovini/blog?a=YYhjl8lltoQ:ikXTLRQZWmQ:qj6IDK7rITs"><img src="http://feeds.feedburner.com/~ff/cvedovini/blog?d=qj6IDK7rITs" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/cvedovini/blog?a=YYhjl8lltoQ:ikXTLRQZWmQ:gIN9vFwOqvQ"><img src="http://feeds.feedburner.com/~ff/cvedovini/blog?i=YYhjl8lltoQ:ikXTLRQZWmQ:gIN9vFwOqvQ" border="0"></img></a>
</div>]]></content:encoded> <wfw:commentRss>http://vedovini.net/2011/10/the-network-of-trust/feed/</wfw:commentRss> <slash:comments>0</slash:comments> <feedburner:origLink>http://vedovini.net/2011/10/the-network-of-trust/</feedburner:origLink></item> <item><title>And you think 160 is not enough?</title><link>http://feedproxy.google.com/~r/cvedovini/blog/~3/sYgMtHwL5zE/</link> <comments>http://vedovini.net/2010/10/sms-messages-are-not-160-characters-long/#comments</comments> <pubDate>Tue, 19 Oct 2010 11:54:40 +0000</pubDate> <dc:creator>Claude</dc:creator> <category><![CDATA[technology]]></category> <category><![CDATA[encoding]]></category> <category><![CDATA[iphone]]></category> <category><![CDATA[mobile]]></category> <category><![CDATA[sms]]></category><guid isPermaLink="false">http://vedovini.net/?p=691</guid> <description><![CDATA[SMS are not 160 characters long, they are 140 bytes long! This is what I discovered today after my SO complained that her mobile operator was charging her for SMS she never sent&#8230; And when you know how computers are working, it totally makes sense! &#8220;So what?&#8221; are you going to ask? So, this is again [...]]]></description> <content:encoded><![CDATA[<p><strong><a href="http://www.flickr.com/photos/webel/1150281459/"><img class="alignright" title="SMS by Steve Webel" src="http://farm2.static.flickr.com/1362/1150281459_9fbca61690_m_d.jpg" alt="" width="240" height="161" /></a>SMS are not 160 characters long, they are 140 <span style="text-decoration: underline;">bytes</span> long! This is what I discovered today after <strong>my SO complained that her mobile operator was charging her for SMS she never sent&#8230;</strong></strong></p><p>And when you know how computers are working, it totally makes sense!</p><p>&#8220;So what?&#8221; are you going to ask? So, this is again a nice example of character encodings drive you crazy. According to <a href="http://en.wikipedia.org/wiki/SMS#Message_size">wikipedia</a> there are 3 encodings used in text messages which respectively use 7bits, 8bits and 16bits to encode a single character.</p><p>Depending on the characters you used in your message your phone is going to decide what encoding to use, thus reducing the maximum number of characters to, respectively, 160, 140 and 70 (and even less, see later). Any extra character will lead to the splitting of your message into multiple SMS and, obviously, a raise in your bill.</p><p>By default the 7bit encoding used is <a href="http://en.wikipedia.org/wiki/GSM_03.38">GSM 03.38</a>, which has the following 128 characters alphabet: @, £, $, ¥, è, é, ù, ì, ò, Ç, LF, Ø, ø, CR, Å, å, Δ, _, Φ, Γ, Λ, Ω, Π, Ψ, Σ, Θ, Ξ, ESC, Æ, æ, ß, É, SP, !, &#8220;, #, ¤, %, &amp;, &#8216;, (, ), *, +, ,, -, ., /, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, :, ;, &lt;, =, &gt;, ?, ¡, A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z, Ä, Ö, Ñ, Ü, §, ¿, a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x, y, z, ä, ö, ñ, ü, à</p><p>If you use only those characters, then you text messages can have 160 characters, however, any character outside of this alphabet will mean the use of a different encoding. And if you are using exotic scripts, your messages will be encoded in UTF-16 and in this encoding a Chinese character, for example, will take up to 4 bytes, reducing the maximum length of you Chinese message to 35 characters max.</p><p>I guess that now that smart phones are supporting international scripts and transparently breaking up text messages, a lot of people get trapped. The only recommendation I can think of is to enable your phone to display the character count when you type text messages, I noticed that my iPhone is changing the maximum number of characters according to the encoding it&#8217;s going to use to send my message.</p><p>If you want to know more about character encodings I absolutely recommend the following article by Joel Spolsky: <a href="http://www.joelonsoftware.com/articles/Unicode.html">The Absolute Minimum Every Software Developer Absolutely, Positively Must Know About Unicode and Character Sets (No Excuses!)</a></p><p><strong>UPDATE: At Stephanie&#8217;s request here is how to activate message count on your iPhone (at least on my 3GS with iOS 4.1).</strong></p><p>Go to your iPhone settings, scroll down to &#8220;Messages&#8221; then toggle &#8220;Character Count&#8221; on. When you write a text message the count will show up only if you have at least two lines of text :)</p><p><a href="http://www.flickr.com/photos/cvedovini/5098205012/"><img class="aligncenter" src="http://farm2.static.flickr.com/1389/5098205012_c0e7ee66af_d.jpg" alt="" width="500" height="250" /></a></p><h3  class="related_post_title">Related posts: (automatically generated)</h3><ul class="related_post"><li><a href="http://vedovini.net/2009/05/jus-dorange-ou-citron-presse/" title="Jus d&#8217;Orange ou citron pressé?">Jus d&#8217;Orange ou citron pressé?</a></li><li><a href="http://vedovini.net/2008/04/fun-with-java-files-encoding/" title="Fun with Java files encoding">Fun with Java files encoding</a></li></ul><div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/cvedovini/blog?a=sYgMtHwL5zE:8RFsOPKm--w:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/cvedovini/blog?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/cvedovini/blog?a=sYgMtHwL5zE:8RFsOPKm--w:F7zBnMyn0Lo"><img src="http://feeds.feedburner.com/~ff/cvedovini/blog?i=sYgMtHwL5zE:8RFsOPKm--w:F7zBnMyn0Lo" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/cvedovini/blog?a=sYgMtHwL5zE:8RFsOPKm--w:V_sGLiPBpWU"><img src="http://feeds.feedburner.com/~ff/cvedovini/blog?i=sYgMtHwL5zE:8RFsOPKm--w:V_sGLiPBpWU" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/cvedovini/blog?a=sYgMtHwL5zE:8RFsOPKm--w:qj6IDK7rITs"><img src="http://feeds.feedburner.com/~ff/cvedovini/blog?d=qj6IDK7rITs" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/cvedovini/blog?a=sYgMtHwL5zE:8RFsOPKm--w:gIN9vFwOqvQ"><img src="http://feeds.feedburner.com/~ff/cvedovini/blog?i=sYgMtHwL5zE:8RFsOPKm--w:gIN9vFwOqvQ" border="0"></img></a>
</div>]]></content:encoded> <wfw:commentRss>http://vedovini.net/2010/10/sms-messages-are-not-160-characters-long/feed/</wfw:commentRss> <slash:comments>3</slash:comments> <feedburner:origLink>http://vedovini.net/2010/10/sms-messages-are-not-160-characters-long/</feedburner:origLink></item> <item><title>What’s your problem, exactly?</title><link>http://feedproxy.google.com/~r/cvedovini/blog/~3/Mj8ps4DB3qk/</link> <comments>http://vedovini.net/2010/10/whats-your-problem/#comments</comments> <pubDate>Wed, 13 Oct 2010 20:05:05 +0000</pubDate> <dc:creator>Claude</dc:creator> <category><![CDATA[random]]></category> <category><![CDATA[bug reporting garage attitude developers]]></category><guid isPermaLink="false">http://vedovini.net/?p=674</guid> <description><![CDATA[When you have a problem with your car and you go to the garage you usually say something along the line of &#8220;I&#8217;ve got a strange noise when I do this or that&#8221;. The guy (or, in my dreams, the gal) never say &#8220;I don&#8217;t understand, come back later with a better description of your [...]]]></description> <content:encoded><![CDATA[<p><a href="http://www.flickr.com/photos/nacmiasmobil/3666108442/"><img class="alignright" title="Nacmias Auto Sales, Service, and Repairs by Rich Nacmias" src="http://farm3.static.flickr.com/2450/3666108442_1fab53477c_m.jpg" alt="" width="180" height="240" /></a><strong>When you have a problem with your car and you go to the garage you usually say something along the line of &#8220;I&#8217;ve got a strange noise when I do this or that&#8221;. The guy (or, in my dreams,  the gal) never say &#8220;I don&#8217;t understand, come back later with a better description of your problem&#8221;.</strong></p><p>To my fellow developers: this is the same when a user comes to you with a bug. Believe me, there&#8217;s no such thing as an under-specified bug.</p><p>There&#8217;s a rampant habit among developers for being condescendant and asking for precisely specified bug reports. I know it, I do it as well. Developers have a lot of reason to do that, but mostly it&#8217;s because we think we are smarter than average (which is true, most of the time) and you don&#8217;t deserve our attention if you&#8217;re too stupid to understand the way we work. The other thing is that we don&#8217;t like bugs, and one way to avoid bugs is to make it difficult to report them.</p><p>When a user (or client, which is worse) take the time to come  to you and say there&#8217;s a problem with your software, take their word for granted. Even if it&#8217;s not a technical bug it can be a documentation or an education bug. Make sure it&#8217;s easy and worthwhile for them to report that bug because, before all, it&#8217;s in your own interest.</p><p>Reporting a bug must be a conversation. I mean, you would go to another garage if the guy was condescendant, disrespectful or was simply oblivious, wouldn&#8217;t you?</p><h3  class="related_post_title">Most Commented Posts</h3><ul class="related_post"><li><a href="http://vedovini.net/2010/02/sevices-apres-vente/" title="Sévices Après Vente">Sévices Après Vente</a></li><li><a href="http://vedovini.net/2009/08/jmeter-distributed-testing-with-amazon-ec2/" title="JMeter distributed testing with Amazon EC2">JMeter distributed testing with Amazon EC2</a></li><li><a href="http://vedovini.net/2008/09/google-please-no/" title="Google, please, NO!">Google, please, NO!</a></li></ul><div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/cvedovini/blog?a=Mj8ps4DB3qk:YzAP5p0oL14:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/cvedovini/blog?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/cvedovini/blog?a=Mj8ps4DB3qk:YzAP5p0oL14:F7zBnMyn0Lo"><img src="http://feeds.feedburner.com/~ff/cvedovini/blog?i=Mj8ps4DB3qk:YzAP5p0oL14:F7zBnMyn0Lo" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/cvedovini/blog?a=Mj8ps4DB3qk:YzAP5p0oL14:V_sGLiPBpWU"><img src="http://feeds.feedburner.com/~ff/cvedovini/blog?i=Mj8ps4DB3qk:YzAP5p0oL14:V_sGLiPBpWU" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/cvedovini/blog?a=Mj8ps4DB3qk:YzAP5p0oL14:qj6IDK7rITs"><img src="http://feeds.feedburner.com/~ff/cvedovini/blog?d=qj6IDK7rITs" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/cvedovini/blog?a=Mj8ps4DB3qk:YzAP5p0oL14:gIN9vFwOqvQ"><img src="http://feeds.feedburner.com/~ff/cvedovini/blog?i=Mj8ps4DB3qk:YzAP5p0oL14:gIN9vFwOqvQ" border="0"></img></a>
</div>]]></content:encoded> <wfw:commentRss>http://vedovini.net/2010/10/whats-your-problem/feed/</wfw:commentRss> <slash:comments>1</slash:comments> <feedburner:origLink>http://vedovini.net/2010/10/whats-your-problem/</feedburner:origLink></item> <item><title>Facebook Pages Notifications</title><link>http://feedproxy.google.com/~r/cvedovini/blog/~3/jep0yVR6HeA/</link> <comments>http://vedovini.net/2010/07/facebook-pages-notifications/#comments</comments> <pubDate>Fri, 16 Jul 2010 14:57:32 +0000</pubDate> <dc:creator>Claude</dc:creator> <category><![CDATA[portfolio]]></category> <category><![CDATA[application]]></category> <category><![CDATA[comment]]></category> <category><![CDATA[e-mail]]></category> <category><![CDATA[facebook]]></category> <category><![CDATA[notifications]]></category> <category><![CDATA[page notifier]]></category> <category><![CDATA[pages]]></category> <category><![CDATA[status]]></category> <category><![CDATA[wall]]></category> <category><![CDATA[watch my pages!]]></category><guid isPermaLink="false">http://vedovini.net/?p=660</guid> <description><![CDATA[You might have noticed already, if you administer community or professional pages or have developed Facebook applications, that contrary to your own personal wall you never get notified when someone post a status or write a comment on your pages? This is a problem for most page administrators and there is a 32 pages long [...]]]></description> <content:encoded><![CDATA[<p><strong> <a href="http://www.facebook.com/apps/application.php?id=142015502480156"><img class="alignright size-full wp-image-706" title="logo" src="http://static.vedovini.net/blog/wp-content/uploads/2010/07/logo.png" alt="" width="300" height="300" /></a>You might have noticed already, if you administer community or professional pages or have developed Facebook applications, that contrary to your own personal wall you never get notified when someone post a status or write a comment on your pages?</strong></p><p>This is a problem for most page administrators and there is a <a href="http://www.facebook.com/topic.php?uid=10381469571&amp;topic=6070">32 pages long (and growing) thread</a> with people complaining about this missing feature. This is a problem because without such a feature you have to periodically crawl your own pages to check if anyone posted anything (status or comment) and get the opportunity to eventually respond to it, or spam it. I guess that since they won&#8217;t get notified about this thread the Facebook people will never notice the problem&#8230;</p><p>One proposed solution to this issue is to &#8220;like&#8221; each and every status update you post on your pages wall, however, beside the fact that liking everything you post may look a bit awkward, this does not gets you notified when someone posts a new status.</p><p>I have some pages I need to watch, so missing this feature was really a problem to me. And when it itches, I scratch&#8230; Besides, I wanted to experiment with the new Facebook Graph API.</p><p>So I created <a href="http://apps.facebook.com/fbpagewatch/">this application</a>, it&#8217;s called &#8220;Watch My Pages!&#8221; and provides users with receiving daily e-mail notifications when someone posts a status or writes a comment to their pages wall. If you like it, have a problem with it or think about a feature, just <a href="http://www.facebook.com/apps/application.php?id=142015502480156">drop a message on it&#8217;s wall</a>, I&#8217;ll get notified ;)</p><h3  class="related_post_title">Related posts: (automatically generated)</h3><ul class="related_post"><li><a href="http://vedovini.net/2010/01/experiencing-viral-growth/" title="Experiencing viral growth">Experiencing viral growth</a></li><li><a href="http://vedovini.net/2009/12/a-year-in-review/" title="A year in review">A year in review</a></li><li><a href="http://vedovini.net/2009/03/vedovininet-is-on-facebook/" title="vedovini.net is on Facebook">vedovini.net is on Facebook</a></li></ul><div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/cvedovini/blog?a=jep0yVR6HeA:4oIrsbyz2AM:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/cvedovini/blog?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/cvedovini/blog?a=jep0yVR6HeA:4oIrsbyz2AM:F7zBnMyn0Lo"><img src="http://feeds.feedburner.com/~ff/cvedovini/blog?i=jep0yVR6HeA:4oIrsbyz2AM:F7zBnMyn0Lo" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/cvedovini/blog?a=jep0yVR6HeA:4oIrsbyz2AM:V_sGLiPBpWU"><img src="http://feeds.feedburner.com/~ff/cvedovini/blog?i=jep0yVR6HeA:4oIrsbyz2AM:V_sGLiPBpWU" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/cvedovini/blog?a=jep0yVR6HeA:4oIrsbyz2AM:qj6IDK7rITs"><img src="http://feeds.feedburner.com/~ff/cvedovini/blog?d=qj6IDK7rITs" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/cvedovini/blog?a=jep0yVR6HeA:4oIrsbyz2AM:gIN9vFwOqvQ"><img src="http://feeds.feedburner.com/~ff/cvedovini/blog?i=jep0yVR6HeA:4oIrsbyz2AM:gIN9vFwOqvQ" border="0"></img></a>
</div>]]></content:encoded> <wfw:commentRss>http://vedovini.net/2010/07/facebook-pages-notifications/feed/</wfw:commentRss> <slash:comments>2</slash:comments> <feedburner:origLink>http://vedovini.net/2010/07/facebook-pages-notifications/</feedburner:origLink></item> <item><title>How to manage Google AppEngine maintenance periods</title><link>http://feedproxy.google.com/~r/cvedovini/blog/~3/BKk1xcc6A0s/</link> <comments>http://vedovini.net/2010/06/how-to-manage-google-appengine-maintenance-periods/#comments</comments> <pubDate>Wed, 30 Jun 2010 21:38:45 +0000</pubDate> <dc:creator>Claude</dc:creator> <category><![CDATA[technology]]></category> <category><![CDATA[appengine]]></category> <category><![CDATA[datastore]]></category> <category><![CDATA[decorator]]></category> <category><![CDATA[django]]></category> <category><![CDATA[gae]]></category> <category><![CDATA[maintenance]]></category> <category><![CDATA[python]]></category> <category><![CDATA[read-only]]></category><guid isPermaLink="false">http://vedovini.net/?p=645</guid> <description><![CDATA[Here is a small snippet of code that I use on applications deployed on Google AppEngine to inform users that the application is in maintenance mode. It usually happen when the AppEngine team put the datastore in read-only mode for maintenance purpose but other capabilities can be tested as well. def requires_datastore_write&#40;view&#41;: def newview&#40;request, *args, [...]]]></description> <content:encoded><![CDATA[<p><img class="alignright size-full wp-image-773" src="http://static.vedovini.net/blog/wp-content/uploads/2010/06/appengine_lowres.png" alt="AppEngine logo" width="142" height="109" /><strong>Here is a small snippet of code that I use on applications deployed on Google AppEngine to inform users that the application is in maintenance mode. </strong></p><p><strong></strong>It usually happen when the AppEngine team put the datastore in read-only mode for maintenance purpose but other capabilities can be tested as well.</p><div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">def</span> requires_datastore_write<span style="color: black;">&#40;</span>view<span style="color: black;">&#41;</span>:
    <span style="color: #ff7700;font-weight:bold;">def</span> newview<span style="color: black;">&#40;</span>request, <span style="color: #66cc66;">*</span>args, <span style="color: #66cc66;">**</span>kwargs<span style="color: black;">&#41;</span>:
        <span style="color: #ff7700;font-weight:bold;">from</span> google.<span style="color: black;">appengine</span>.<span style="color: black;">api</span> <span style="color: #ff7700;font-weight:bold;">import</span> capabilities
        datastore_write_enabled = capabilities.<span style="color: black;">CapabilitySet</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'datastore_v3'</span>, capabilities=<span style="color: black;">&#91;</span><span style="color: #483d8b;">'write'</span><span style="color: black;">&#93;</span><span style="color: black;">&#41;</span>.<span style="color: black;">is_enabled</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
&nbsp;
        <span style="color: #ff7700;font-weight:bold;">if</span> datastore_write_enabled:
            <span style="color: #ff7700;font-weight:bold;">return</span> view<span style="color: black;">&#40;</span>request, <span style="color: #66cc66;">*</span>args, <span style="color: #66cc66;">**</span>kwargs<span style="color: black;">&#41;</span>
        <span style="color: #ff7700;font-weight:bold;">else</span>:
            <span style="color: #ff7700;font-weight:bold;">from</span> django.<span style="color: black;">shortcuts</span> <span style="color: #ff7700;font-weight:bold;">import</span> render_to_response
            <span style="color: #ff7700;font-weight:bold;">from</span> django.<span style="color: black;">template</span> <span style="color: #ff7700;font-weight:bold;">import</span> RequestContext
            <span style="color: #ff7700;font-weight:bold;">return</span> render_to_response<span style="color: black;">&#40;</span><span style="color: #483d8b;">'maintenance.html'</span>, context_instance=RequestContext<span style="color: black;">&#40;</span>request<span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">return</span> newview</pre></div></div><p>This is a python decorator and you can use it to decorate views that require write access to the datastore. For example:</p><div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;">@requires_datastore_write
<span style="color: #ff7700;font-weight:bold;">def</span> update<span style="color: black;">&#40;</span>request<span style="color: black;">&#41;</span>:
    ...</pre></div></div><p>You will need to create a Django template named<br /> <samp>maintenance.html</samp></p><p>to display a warning to your users. Mine looks like this:</p><h2>Application Maintenance</h2><div class="wp_syntax"><div class="code"><pre class="xml" style="font-family:monospace;">The LibraryThing for Facebook application is currently
in maintenance mode and some operations are temporarily unavailable.
&nbsp;
Thanks for trying back later. Sorry for the inconvenience.</pre></div></div><h3  class="related_post_title">Related posts: (automatically generated)</h3><ul class="related_post"><li><a href="http://vedovini.net/2009/12/a-year-in-review/" title="A year in review">A year in review</a></li><li><a href="http://vedovini.net/2010/06/properly-uploading-files-to-amazon-s3/" title="Properly uploading files to Amazon S3">Properly uploading files to Amazon S3</a></li><li><a href="http://vedovini.net/2009/04/i-can-haz-java/" title="I Can Haz Java?">I Can Haz Java?</a></li></ul><div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/cvedovini/blog?a=BKk1xcc6A0s:T_Pe3pYcAro:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/cvedovini/blog?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/cvedovini/blog?a=BKk1xcc6A0s:T_Pe3pYcAro:F7zBnMyn0Lo"><img src="http://feeds.feedburner.com/~ff/cvedovini/blog?i=BKk1xcc6A0s:T_Pe3pYcAro:F7zBnMyn0Lo" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/cvedovini/blog?a=BKk1xcc6A0s:T_Pe3pYcAro:V_sGLiPBpWU"><img src="http://feeds.feedburner.com/~ff/cvedovini/blog?i=BKk1xcc6A0s:T_Pe3pYcAro:V_sGLiPBpWU" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/cvedovini/blog?a=BKk1xcc6A0s:T_Pe3pYcAro:qj6IDK7rITs"><img src="http://feeds.feedburner.com/~ff/cvedovini/blog?d=qj6IDK7rITs" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/cvedovini/blog?a=BKk1xcc6A0s:T_Pe3pYcAro:gIN9vFwOqvQ"><img src="http://feeds.feedburner.com/~ff/cvedovini/blog?i=BKk1xcc6A0s:T_Pe3pYcAro:gIN9vFwOqvQ" border="0"></img></a>
</div>]]></content:encoded> <wfw:commentRss>http://vedovini.net/2010/06/how-to-manage-google-appengine-maintenance-periods/feed/</wfw:commentRss> <slash:comments>0</slash:comments> <feedburner:origLink>http://vedovini.net/2010/06/how-to-manage-google-appengine-maintenance-periods/</feedburner:origLink></item> <item><title>Properly uploading files to Amazon S3</title><link>http://feedproxy.google.com/~r/cvedovini/blog/~3/5ts_S-gmNBs/</link> <comments>http://vedovini.net/2010/06/properly-uploading-files-to-amazon-s3/#comments</comments> <pubDate>Tue, 22 Jun 2010 10:27:37 +0000</pubDate> <dc:creator>Claude</dc:creator> <category><![CDATA[technology]]></category> <category><![CDATA[aws]]></category> <category><![CDATA[boto]]></category> <category><![CDATA[cssmin]]></category> <category><![CDATA[gzip]]></category> <category><![CDATA[jsmin]]></category> <category><![CDATA[minify]]></category> <category><![CDATA[python]]></category> <category><![CDATA[s3]]></category><guid isPermaLink="false">http://vedovini.net/?p=624</guid> <description><![CDATA[Here is a little script I wrote and I though ought to be shared. I use it to upload static files like images, css and javascript so that they can be served by Amazon S3 instead of the main application server (like Google App Engine). It&#8217;s written in Python and does interesting things like compressing [...]]]></description> <content:encoded><![CDATA[<p><strong>Here is a little script I wrote and I though ought to be shared. I use it to upload static files like images, css and javascript so that they can be served by Amazon S3 instead of the main application server (like Google App Engine).</strong></p><p>It&#8217;s written in Python and does interesting things like compressing and minifying what needs to be. It takes 3 arguments and as 2 options:</p><div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;">Usage: s3uploader.py <span style="color: #7a0874; font-weight: bold;">&#91;</span>-xm<span style="color: #7a0874; font-weight: bold;">&#93;</span> src_folder destination_bucket_name prefix</pre></div></div><dl><dt>src_folder</dt><dd>path to the local folder containing the static files to upload</dd><dt>destination_bucket_name</dt><dd>name of the S3 bucket to upload to (e.g. static.example.com)</dd><dt>prefix</dt><dd>a prefix to use for the destination key (kind of a folder on the destination bucket, I use it to specify a release version to defeat browser caching)</dd><dt>x</dt><dd>if set, the script will set a far future expiry for all files, otherwise the S3 default will be used (one day if I remember well)</dd><dt>m</dt><dd>if set, the script will minify css and javascript files</dd></dl><p>First you will have to install some dependencies, namely boto, jsmin and cssmin. Installation procedure will depend on your OS but on my Mac I do the following:</p><div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;"><span style="color: #c20cb9; font-weight: bold;">sudo</span> easy_install boto
<span style="color: #c20cb9; font-weight: bold;">sudo</span> easy_install jsmin
<span style="color: #c20cb9; font-weight: bold;">sudo</span> easy_install cssmin</pre></div></div><p>And here is the script itself:</p><div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #808080; font-style: italic;">#! /usr/bin/env python</span>
<span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">os</span>, <span style="color: #dc143c;">sys</span>, boto, <span style="color: #dc143c;">mimetypes</span>, <span style="color: #dc143c;">zipfile</span>, <span style="color: #dc143c;">gzip</span>
<span style="color: #ff7700;font-weight:bold;">from</span> io <span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">StringIO</span>, BytesIO
<span style="color: #ff7700;font-weight:bold;">from</span> <span style="color: #dc143c;">optparse</span> <span style="color: #ff7700;font-weight:bold;">import</span> OptionParser
<span style="color: #ff7700;font-weight:bold;">from</span> jsmin <span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #66cc66;">*</span>
<span style="color: #ff7700;font-weight:bold;">from</span> cssmin <span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #66cc66;">*</span>
&nbsp;
<span style="color: #808080; font-style: italic;"># Boto picks up configuration from the env.</span>
<span style="color: #dc143c;">os</span>.<span style="color: black;">environ</span><span style="color: black;">&#91;</span><span style="color: #483d8b;">'AWS_ACCESS_KEY_ID'</span><span style="color: black;">&#93;</span> = <span style="color: #483d8b;">'Your AWS access key id goes here'</span>
<span style="color: #dc143c;">os</span>.<span style="color: black;">environ</span><span style="color: black;">&#91;</span><span style="color: #483d8b;">'AWS_SECRET_ACCESS_KEY'</span><span style="color: black;">&#93;</span> = <span style="color: #483d8b;">'Your AWS secret access key goes here'</span>
&nbsp;
<span style="color: #808080; font-style: italic;"># The list of content types to gzip, add more if needed</span>
COMPRESSIBLE = <span style="color: black;">&#91;</span> <span style="color: #483d8b;">'text/plain'</span>, <span style="color: #483d8b;">'text/csv'</span>, <span style="color: #483d8b;">'application/xml'</span>,
                <span style="color: #483d8b;">'application/javascript'</span>, <span style="color: #483d8b;">'text/css'</span> <span style="color: black;">&#93;</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">def</span> main<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>:
    <span style="color: #dc143c;">parser</span> = OptionParser<span style="color: black;">&#40;</span>usage=<span style="color: #483d8b;">'usage: %prog [options] src_folder destination_bucket_name prefix'</span><span style="color: black;">&#41;</span>
    <span style="color: #dc143c;">parser</span>.<span style="color: black;">add_option</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'-x'</span>, <span style="color: #483d8b;">'--expires'</span>, action=<span style="color: #483d8b;">'store_true'</span>, <span style="color: #008000;">help</span>=<span style="color: #483d8b;">'set far future expiry for all files'</span><span style="color: black;">&#41;</span>
    <span style="color: #dc143c;">parser</span>.<span style="color: black;">add_option</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'-m'</span>, <span style="color: #483d8b;">'--minify'</span>, action=<span style="color: #483d8b;">'store_true'</span>, <span style="color: #008000;">help</span>=<span style="color: #483d8b;">'minify javascript files'</span><span style="color: black;">&#41;</span>
    <span style="color: black;">&#40;</span>options, args<span style="color: black;">&#41;</span> = <span style="color: #dc143c;">parser</span>.<span style="color: black;">parse_args</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
    <span style="color: #ff7700;font-weight:bold;">if</span> <span style="color: #008000;">len</span><span style="color: black;">&#40;</span>args<span style="color: black;">&#41;</span> <span style="color: #66cc66;">!</span>= <span style="color: #ff4500;">3</span>:
        <span style="color: #dc143c;">parser</span>.<span style="color: black;">error</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;incorrect number of arguments&quot;</span><span style="color: black;">&#41;</span>
    src_folder = <span style="color: #dc143c;">os</span>.<span style="color: black;">path</span>.<span style="color: black;">normpath</span><span style="color: black;">&#40;</span>args<span style="color: black;">&#91;</span><span style="color: #ff4500;">0</span><span style="color: black;">&#93;</span><span style="color: black;">&#41;</span>
    bucket_name = args<span style="color: black;">&#91;</span><span style="color: #ff4500;">1</span><span style="color: black;">&#93;</span>
    prefix = args<span style="color: black;">&#91;</span><span style="color: #ff4500;">2</span><span style="color: black;">&#93;</span>
&nbsp;
    conn = boto.<span style="color: black;">connect_s3</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
    bucket = conn.<span style="color: black;">get_bucket</span><span style="color: black;">&#40;</span>bucket_name<span style="color: black;">&#41;</span>
&nbsp;
    namelist = <span style="color: black;">&#91;</span><span style="color: black;">&#93;</span>
    <span style="color: #ff7700;font-weight:bold;">for</span> root, dirs, files <span style="color: #ff7700;font-weight:bold;">in</span> <span style="color: #dc143c;">os</span>.<span style="color: black;">walk</span><span style="color: black;">&#40;</span>src_folder<span style="color: black;">&#41;</span>:
        <span style="color: #ff7700;font-weight:bold;">if</span> files <span style="color: #ff7700;font-weight:bold;">and</span> <span style="color: #ff7700;font-weight:bold;">not</span> <span style="color: #483d8b;">'.svn'</span> <span style="color: #ff7700;font-weight:bold;">in</span> root:
            path = <span style="color: #dc143c;">os</span>.<span style="color: black;">path</span>.<span style="color: black;">relpath</span><span style="color: black;">&#40;</span>root, src_folder<span style="color: black;">&#41;</span>
            namelist += <span style="color: black;">&#91;</span><span style="color: #dc143c;">os</span>.<span style="color: black;">path</span>.<span style="color: black;">normpath</span><span style="color: black;">&#40;</span><span style="color: #dc143c;">os</span>.<span style="color: black;">path</span>.<span style="color: black;">join</span><span style="color: black;">&#40;</span>path, f<span style="color: black;">&#41;</span><span style="color: black;">&#41;</span> <span style="color: #ff7700;font-weight:bold;">for</span> f <span style="color: #ff7700;font-weight:bold;">in</span> files<span style="color: black;">&#93;</span>
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">print</span> <span style="color: #483d8b;">'Uploading %d files to bucket %s'</span> <span style="color: #66cc66;">%</span> <span style="color: black;">&#40;</span><span style="color: #008000;">len</span><span style="color: black;">&#40;</span>namelist<span style="color: black;">&#41;</span>, bucket.<span style="color: black;">name</span><span style="color: black;">&#41;</span>
    <span style="color: #ff7700;font-weight:bold;">for</span> name <span style="color: #ff7700;font-weight:bold;">in</span> namelist:
        content = <span style="color: #008000;">open</span><span style="color: black;">&#40;</span><span style="color: #dc143c;">os</span>.<span style="color: black;">path</span>.<span style="color: black;">join</span><span style="color: black;">&#40;</span>src_folder, name<span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
        key = bucket.<span style="color: black;">new_key</span><span style="color: black;">&#40;</span><span style="color: #dc143c;">os</span>.<span style="color: black;">path</span>.<span style="color: black;">join</span><span style="color: black;">&#40;</span>prefix, name<span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
        <span style="color: #008000;">type</span>, encoding = <span style="color: #dc143c;">mimetypes</span>.<span style="color: black;">guess_type</span><span style="color: black;">&#40;</span>name<span style="color: black;">&#41;</span>
        <span style="color: #008000;">type</span> = <span style="color: #008000;">type</span> <span style="color: #ff7700;font-weight:bold;">or</span> <span style="color: #483d8b;">'application/octet-stream'</span>
        headers = <span style="color: black;">&#123;</span> <span style="color: #483d8b;">'Content-Type'</span>: <span style="color: #008000;">type</span>, <span style="color: #483d8b;">'x-amz-acl'</span>: <span style="color: #483d8b;">'public-read'</span> <span style="color: black;">&#125;</span>
        states = <span style="color: black;">&#91;</span><span style="color: #008000;">type</span><span style="color: black;">&#93;</span>
&nbsp;
        <span style="color: #ff7700;font-weight:bold;">if</span> options.<span style="color: black;">expires</span>:
            <span style="color: #808080; font-style: italic;"># We only use HTTP 1.1 headers because they are relative to the time of download</span>
            <span style="color: #808080; font-style: italic;"># instead of being hardcoded.</span>
            headers<span style="color: black;">&#91;</span><span style="color: #483d8b;">'Cache-Control'</span><span style="color: black;">&#93;</span> = <span style="color: #483d8b;">'max-age %d'</span> <span style="color: #66cc66;">%</span> <span style="color: black;">&#40;</span><span style="color: #ff4500;">3600</span> <span style="color: #66cc66;">*</span> <span style="color: #ff4500;">24</span> <span style="color: #66cc66;">*</span> <span style="color: #ff4500;">365</span><span style="color: black;">&#41;</span>
&nbsp;
        <span style="color: #ff7700;font-weight:bold;">if</span> options.<span style="color: black;">minify</span> <span style="color: #ff7700;font-weight:bold;">and</span> <span style="color: #008000;">type</span> == <span style="color: #483d8b;">'application/javascript'</span>:
            outs = <span style="color: #dc143c;">StringIO</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
            JavascriptMinify<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>.<span style="color: black;">minify</span><span style="color: black;">&#40;</span>content, outs<span style="color: black;">&#41;</span>
            content.<span style="color: black;">close</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
            content = outs.<span style="color: black;">getvalue</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
            <span style="color: #ff7700;font-weight:bold;">if</span> <span style="color: #008000;">len</span><span style="color: black;">&#40;</span>content<span style="color: black;">&#41;</span> <span style="color: #66cc66;">&amp;</span>gt<span style="color: #66cc66;">;</span> <span style="color: #ff4500;">0</span> <span style="color: #ff7700;font-weight:bold;">and</span> content<span style="color: black;">&#91;</span><span style="color: #ff4500;">0</span><span style="color: black;">&#93;</span> == <span style="color: #483d8b;">'<span style="color: #000099; font-weight: bold;">\n</span>'</span>:
                content = content<span style="color: black;">&#91;</span><span style="color: #ff4500;">1</span>:<span style="color: black;">&#93;</span>
            content = BytesIO<span style="color: black;">&#40;</span>content<span style="color: black;">&#41;</span>
            states.<span style="color: black;">append</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'minified'</span><span style="color: black;">&#41;</span>
&nbsp;
        <span style="color: #ff7700;font-weight:bold;">if</span> options.<span style="color: black;">minify</span> <span style="color: #ff7700;font-weight:bold;">and</span> <span style="color: #008000;">type</span> == <span style="color: #483d8b;">'text/css'</span>:
            outs = cssmin<span style="color: black;">&#40;</span>content.<span style="color: black;">read</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
            content.<span style="color: black;">close</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
            content = outs
            <span style="color: #ff7700;font-weight:bold;">if</span> <span style="color: #008000;">len</span><span style="color: black;">&#40;</span>content<span style="color: black;">&#41;</span> <span style="color: #66cc66;">&amp;</span>gt<span style="color: #66cc66;">;</span> <span style="color: #ff4500;">0</span> <span style="color: #ff7700;font-weight:bold;">and</span> content<span style="color: black;">&#91;</span><span style="color: #ff4500;">0</span><span style="color: black;">&#93;</span> == <span style="color: #483d8b;">'<span style="color: #000099; font-weight: bold;">\n</span>'</span>:
                content = content<span style="color: black;">&#91;</span><span style="color: #ff4500;">1</span>:<span style="color: black;">&#93;</span>
            content = BytesIO<span style="color: black;">&#40;</span>content<span style="color: black;">&#41;</span>
            states.<span style="color: black;">append</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'minified'</span><span style="color: black;">&#41;</span>
&nbsp;
        <span style="color: #ff7700;font-weight:bold;">if</span> <span style="color: #008000;">type</span> <span style="color: #ff7700;font-weight:bold;">in</span> COMPRESSIBLE:
            headers<span style="color: black;">&#91;</span><span style="color: #483d8b;">'Content-Encoding'</span><span style="color: black;">&#93;</span> = <span style="color: #483d8b;">'gzip'</span>
            compressed = <span style="color: #dc143c;">StringIO</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
            gz = <span style="color: #dc143c;">gzip</span>.<span style="color: black;">GzipFile</span><span style="color: black;">&#40;</span>filename=name, fileobj=compressed, mode=<span style="color: #483d8b;">'w'</span><span style="color: black;">&#41;</span>
            gz.<span style="color: black;">writelines</span><span style="color: black;">&#40;</span>content<span style="color: black;">&#41;</span>
            gz.<span style="color: black;">close</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
            content.<span style="color: black;">close</span>
            content = BytesIO<span style="color: black;">&#40;</span>compressed.<span style="color: black;">getvalue</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
            states.<span style="color: black;">append</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'gzipped'</span><span style="color: black;">&#41;</span>
&nbsp;
        states = <span style="color: #483d8b;">', '</span>.<span style="color: black;">join</span><span style="color: black;">&#40;</span>states<span style="color: black;">&#41;</span>
        <span style="color: #ff7700;font-weight:bold;">print</span> <span style="color: #483d8b;">'- %s =&amp;gt; %s (%s)'</span> <span style="color: #66cc66;">%</span> <span style="color: black;">&#40;</span>name, key.<span style="color: black;">name</span>, states<span style="color: black;">&#41;</span>
        key.<span style="color: black;">set_contents_from_file</span><span style="color: black;">&#40;</span>content, headers<span style="color: black;">&#41;</span>
        content.<span style="color: black;">close</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span><span style="color: #66cc66;">;</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">if</span> __name__ == <span style="color: #483d8b;">'__main__'</span>:
    main<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span></pre></div></div><p>Thanks to Nico for the expiry trick :)</p><h3  class="related_post_title">Related posts: (automatically generated)</h3><ul class="related_post"><li><a href="http://vedovini.net/2009/12/a-year-in-review/" title="A year in review">A year in review</a></li><li><a href="http://vedovini.net/2010/06/how-to-manage-google-appengine-maintenance-periods/" title="How to manage Google AppEngine maintenance periods">How to manage Google AppEngine maintenance periods</a></li></ul><div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/cvedovini/blog?a=5ts_S-gmNBs:2qoL_1bRaUk:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/cvedovini/blog?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/cvedovini/blog?a=5ts_S-gmNBs:2qoL_1bRaUk:F7zBnMyn0Lo"><img src="http://feeds.feedburner.com/~ff/cvedovini/blog?i=5ts_S-gmNBs:2qoL_1bRaUk:F7zBnMyn0Lo" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/cvedovini/blog?a=5ts_S-gmNBs:2qoL_1bRaUk:V_sGLiPBpWU"><img src="http://feeds.feedburner.com/~ff/cvedovini/blog?i=5ts_S-gmNBs:2qoL_1bRaUk:V_sGLiPBpWU" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/cvedovini/blog?a=5ts_S-gmNBs:2qoL_1bRaUk:qj6IDK7rITs"><img src="http://feeds.feedburner.com/~ff/cvedovini/blog?d=qj6IDK7rITs" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/cvedovini/blog?a=5ts_S-gmNBs:2qoL_1bRaUk:gIN9vFwOqvQ"><img src="http://feeds.feedburner.com/~ff/cvedovini/blog?i=5ts_S-gmNBs:2qoL_1bRaUk:gIN9vFwOqvQ" border="0"></img></a>
</div>]]></content:encoded> <wfw:commentRss>http://vedovini.net/2010/06/properly-uploading-files-to-amazon-s3/feed/</wfw:commentRss> <slash:comments>0</slash:comments> <feedburner:origLink>http://vedovini.net/2010/06/properly-uploading-files-to-amazon-s3/</feedburner:origLink></item> <item><title>Spare me the talk about privacy, they’re all clueless anyway…</title><link>http://feedproxy.google.com/~r/cvedovini/blog/~3/q2Qgsez--OQ/</link> <comments>http://vedovini.net/2010/02/spare-me-the-talk-about-privacy-theyre-all-clueless-anyway/#comments</comments> <pubDate>Tue, 02 Feb 2010 11:10:19 +0000</pubDate> <dc:creator>Claude</dc:creator> <category><![CDATA[rants]]></category> <category><![CDATA[clueless]]></category> <category><![CDATA[data mining]]></category> <category><![CDATA[google]]></category> <category><![CDATA[privacy]]></category><guid isPermaLink="false">http://vedovini.net/?p=548</guid> <description><![CDATA[With all the talks and posts and whatnot about privacy on the Internet it&#8217;s easy for anyone to turn into a privacy control freak. And I really was starting to freak out myself. After all, a good bunch of my own life is on the Net: Facebook, Twitter, Flickr, LinkedIn, this blog, all the Google [...]]]></description> <content:encoded><![CDATA[<p><strong><a href="http://www.flickr.com/photos/michellzappa/3224860947/"><img class="alignright" title="PRIVACY: @chassyofcricket by Michell Zappa" src="http://farm4.static.flickr.com/3474/3224860947_1a1e8e014f_m.jpg" alt="" width="240" height="159" /></a>With all the talks and posts and whatnot about privacy on the Internet it&#8217;s easy for anyone to turn into a privacy control freak.</strong></p><p>And I really was starting to freak out myself. After all, a good bunch of my own life is on the Net: Facebook, Twitter, Flickr, LinkedIn, this blog, all the Google applications and all the other services I use, or I test&#8230; But this morning I received a letter, not an e-mail, a paper letter. From Google AdWords. Sent from France. In German!</p><p>I guess they just assumed that since I was living in Switzerland I was talking German, like when ebay.com redirects me to ebay.de, but I don&#8217;t speak nor read German.</p><p>And it reminded me something I learned a long time ago, when I was working for Singularis &#8211; a now defunct start-up that was collecting users preferences about TV programs: You can collect as many data as you want, if you don&#8217;t know how to use it it&#8217;s only worth the cost of the storage.</p><p>And the more you have the harder it is.</p><h3  class="related_post_title">Related posts: (automatically generated)</h3><ul class="related_post"><li><a href="http://vedovini.net/2009/09/sidewiki-rss/" title="Sidewiki RSS">Sidewiki RSS</a></li><li><a href="http://vedovini.net/2009/04/does-google-read-this-blog/" title="Does Google read this blog?">Does Google read this blog?</a></li><li><a href="http://vedovini.net/2009/04/just-google-me/" title="Just Google me!">Just Google me!</a></li></ul><div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/cvedovini/blog?a=q2Qgsez--OQ:FfcWIel0A8g:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/cvedovini/blog?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/cvedovini/blog?a=q2Qgsez--OQ:FfcWIel0A8g:F7zBnMyn0Lo"><img src="http://feeds.feedburner.com/~ff/cvedovini/blog?i=q2Qgsez--OQ:FfcWIel0A8g:F7zBnMyn0Lo" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/cvedovini/blog?a=q2Qgsez--OQ:FfcWIel0A8g:V_sGLiPBpWU"><img src="http://feeds.feedburner.com/~ff/cvedovini/blog?i=q2Qgsez--OQ:FfcWIel0A8g:V_sGLiPBpWU" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/cvedovini/blog?a=q2Qgsez--OQ:FfcWIel0A8g:qj6IDK7rITs"><img src="http://feeds.feedburner.com/~ff/cvedovini/blog?d=qj6IDK7rITs" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/cvedovini/blog?a=q2Qgsez--OQ:FfcWIel0A8g:gIN9vFwOqvQ"><img src="http://feeds.feedburner.com/~ff/cvedovini/blog?i=q2Qgsez--OQ:FfcWIel0A8g:gIN9vFwOqvQ" border="0"></img></a>
</div>]]></content:encoded> <wfw:commentRss>http://vedovini.net/2010/02/spare-me-the-talk-about-privacy-theyre-all-clueless-anyway/feed/</wfw:commentRss> <slash:comments>3</slash:comments> <feedburner:origLink>http://vedovini.net/2010/02/spare-me-the-talk-about-privacy-theyre-all-clueless-anyway/</feedburner:origLink></item> <item><title>Sévices Après Vente</title><link>http://feedproxy.google.com/~r/cvedovini/blog/~3/99Ir9JPxWBk/</link> <comments>http://vedovini.net/2010/02/sevices-apres-vente/#comments</comments> <pubDate>Mon, 01 Feb 2010 14:51:22 +0000</pubDate> <dc:creator>Claude</dc:creator> <category><![CDATA[rants]]></category> <category><![CDATA[arnaque]]></category> <category><![CDATA[fnac]]></category> <category><![CDATA[garantie]]></category> <category><![CDATA[insomnie]]></category> <category><![CDATA[macbook]]></category> <category><![CDATA[memoire vive]]></category> <category><![CDATA[pas content]]></category> <category><![CDATA[sav]]></category><guid isPermaLink="false">http://vedovini.net/?p=515</guid> <description><![CDATA[Dans un monde chaque jour un peu plus numérisé n&#8217;oublions pas que ce sont toujours les même vieux trucs qui fonctionnent: si vis pacem, para bellum! !!Attention!! Ce billet est long et ennuyeux&#8230; Ceux qui me suivent sur Twitter ou Facebook se souviendront qu&#8217;en novembre dernier (le vendredi 13 exactement) mon appartement avait été cambriolé [...]]]></description> <content:encoded><![CDATA[<p><strong>Dans un monde chaque jour un peu plus numérisé n&#8217;oublions pas que ce sont toujours les même vieux trucs qui fonctionnent: si vis pacem, para bellum!</strong></p><p><strong>!!Attention!! Ce billet est long et ennuyeux&#8230;</strong></p><p>Ceux qui me suivent sur <a href="http://www.twitter.com/cvedovini">Twitter</a> ou <a href="http://www.facebook.com/cvedovini">Facebook</a> se souviendront qu&#8217;en novembre dernier (le vendredi 13 exactement) mon appartement avait été cambriolé pendant que j&#8217;étais chez le dentiste (ça fais beaucoup pour un vendredi 13). Parmi les objets qui m&#8217;avaient été volés se trouvait mon MacBook Pro, qui est mon seul et unique outil de travail.</p><p>J&#8217;avais donc rapidement besoin d&#8217;une nouvelle machine. Après avoir fait le tour des revendeurs Apple de la région pour découvrir que seules des configurations de base étaient en stock, je me rend, sans grand espoir, à la <a href="http://fnac.ch/">FNAC</a> de Lausanne.</p><p>Je n&#8217;achète jamais de matériel électronique de ce prix à la FNAC &#8211; en dessous de 200,-CHF le rapport prix/rapidité de l&#8217;achat est assez favorable pour que je ne cherche pas plus loin mais au-delà j&#8217;ai toujours pu trouver moins cher ailleurs. Mais, ce samedi 14, je découvre avec bonheur que la FNAC possède en stock un MacBook Pro dont la configuration approche de très prés la configuration que je recherche: 15&#8243;, 3.06GHZ, 4Go de RAM et un disque dur de 500Go à 7200 tr/mn. Je l&#8217;achète donc, pour le prix de 3299,-CHF (moins le rabais adhérents).</p><p>Le 29 décembre dernier (un mois et demi plus tard), en allant me coucher, je décide de laisser mon MacBook allumé sur la table du salon afin qu&#8217;il puisse participer au réseau <a href="http://vedovini.net/2009/02/what-boinc-are-you/">BOINC</a> et dédier quelques cycles à la recherche extra-terrestre. Je n&#8217;ai pas d&#8217;animaux, pas d&#8217;enfants et la machine est posée sur un endroit dégagé où la ventilation n&#8217;est pas obstruée.</p><p>Le lendemain matin, ayant pris mon petit déjeuner, je m&#8217;en vais consulter mes e-mails. Étrangement, alors qu&#8217;une simple caresse suffit d&#8217;habitude, mon Mac ne veut pas se réveiller. Étonné, je vérifie que je ne l&#8217;ai pas laissé sans alimentation: non, le cordon est bien là, branché et alimenté, il ne s&#8217;agit donc pas d&#8217;un épuisement des batteries. De plus, un ronron très léger m&#8217;indique que la machine semble toujours être en marche. Je force donc un shutdown en maintenant la touche on/off enfoncée et j&#8217;entends distinctement ce petit bruit caractéristique qui signale l&#8217;arrêt d&#8217;un moteur électrique quelque part dans la machine. Je l&#8217;allume de nouveau et là un bruit de moteur se fait également entendre mais à par cela rien, l&#8217;écran reste désespérément aveugle. Après une ou deux autres tentatives aussi infructueuses je décide d&#8217;amener la machine au SAV de la FNAC.</p><p><span id="more-515"></span></p><p><a href="http://static.vedovini.net/blog/wp-content/uploads/2010/02/priseenchargesav.jpg"><img class="alignright size-medium wp-image-521" style="border: 1px solid black;" title="Prise en charge SAV" src="http://static.vedovini.net/blog/wp-content/uploads/2010/02/priseenchargesav-235x300.jpg" alt="" width="235" height="300" /></a>L&#8217;accueil est sympathique et l&#8217;employé, après avoir examiné mon appareil et rempli une feuille de prise en charge indiquant un état d&#8217;usage normal (c&#8217;est important pour la suite) me propose un MacBook de remplacement. J&#8217;hésite, et lui demande combien de temps va prendre la réparation? &#8220;3 à 4 semaines&#8221; &#8211; me répond il. Je m&#8217;étonne et il me dit que c&#8217;est leur fournisseur, <a href="http://www.memoirevive.ch/">Mémoire Vive</a>, qui annonce ces délais. Là je me dis que je ferais peut-être bien d&#8217;y aller moi-même chez Mémoire Vive, c&#8217;est à moins de 500m et je sais qu&#8217;en payant un supplément ils font passer votre cas en urgence. Mais je me dis qu&#8217;après tout je l&#8217;ai acheté à la FNAC, qu&#8217;ils se débrouillent avec, et puis au final si j&#8217;ai une machine de remplacement, peu importe le délais. J&#8217;accepte donc la machine de remplacement et me prépare à attendre 4 semaines.</p><p>4 semaines jour pour jour plus tard (le 27 janvier), toujours sans nouvelles de ma machine, j&#8217;appelle le SAV de la FNAC. J&#8217;ai au bout du fil une femme, sympathique également, qui s&#8217;étonne que je n&#8217;ai toujours pas reçu le devis que leur fournisseur m&#8217;a envoyé. Devis? Il s&#8217;agit d&#8217;une machine sous garantie, pourquoi m&#8217;envoyer un devis?</p><p>Cette personne m&#8217;annonce alors que leur fournisseur (Mémoire Vive, donc) a déterminé que la machine avait subit des dégâts suite à un choc et que donc la garantie est annulée. Moi même sous le choc, je perd un peu mon calme, je m&#8217;insurge, affirme que la machine était intacte, que la feuille de prise en charge rédigée par la SAV le prouve et que donc soit il ne s&#8217;agit pas de ma machine (elle se serai trompée de dossier) ou bien que c&#8217;est la FNAC ou son fournisseur qui ont endommagé mon Mac. Elle m&#8217;annonce qu&#8217;il y a une photo et qu&#8217;elle va me l&#8217;envoyer par e-mail avec une copie du devis, je raccroche et attend donc son e-mail.</p><p><a href="http://static.vedovini.net/blog/wp-content/uploads/2010/02/devismacbook.jpg"><img class="size-medium wp-image-526 alignleft" style="border: 1px solid black;" title="Devis MacBook" src="http://static.vedovini.net/blog/wp-content/uploads/2010/02/devismacbook-218x300.jpg" alt="" width="218" height="300" /></a>Le lendemain (28 janvier), toujours pas plus de e-mail que de beurre en branche, par contre, je découvre dans mon courrier le fameux devis qui annonce donc un dommage physique au niveau du port Ethernet et la nécessite de remplacer la carte mère, la barrette mémoire ainsi que le couvercle supérieur: 3449,-CHF pièce et main d&#8217;œuvre.</p><p>Mes choix sont les suivants, soit je paye la réparation, soit je paye le devis (100,-CHF). Si je refuse la réparation il me reste à choisir entre reprendre ma machine ou les laisser la détruire&#8230;</p><p>Je rappel alors le SAV et tombe sur la même personne, qui s&#8217;excuse de ne pas avoir envoyé la photo et qui m&#8217;assure que c&#8217;est parce qu&#8217;ils sont en train d&#8217;étudier mon dossier. Je lui répète une fois de plus qu&#8217;il y a un problème, lui demande de m&#8217;envoyer rapidement la photo dont elle m&#8217;a parlé et raccroche.</p><p><a href="http://static.vedovini.net/blog/wp-content/uploads/2010/02/chocmacbook.jpg"><img class="alignright size-medium wp-image-523" title="Choc MacBook" src="http://static.vedovini.net/blog/wp-content/uploads/2010/02/chocmacbook-300x225.jpg" alt="" width="300" height="225" /></a>Je passe sur les détails mais je finis par recevoir cette fameuse photo où on peut effectivement constater un choc tellement important que le châssis du Mac est déformé et sur laquelle visiblement le capot/écran ne se referme plus correctement. Je répond donc au e-mail en confirmant, une fois de plus, que ces dégâts n&#8217;étaient pas présent lorsque j&#8217;ai amené la machine au SAV et qu&#8217;il aurait été difficile à l&#8217;employé du SAV de rater la chose vu leur importance.</p><p>Je reçois finalement le 29 janvier la réponse suivante par e-mail:</p><blockquote><p>Monsieur Vedovini,</p><p>Pour faire suite à notre conversation téléphonique, nous avons donc contacté le réparateur. Ce dernier nous a transmis des détails concernant votre dossier et devis.</p><p>Aucun dégât n’a pu se produit durant le transport ou durant le transit de votre appareil au réparateur. Les appareils sont emballés par du papier-bulle, protégés par un emballage, puis par un box résistant à toute pression.</p><p>De plus, le défaut cité coïncide avec le refus de prise sous garantie. En effet, la pièce gérant le rétro éclairage se trouve à quelques centimètres de la zone d’impact située à l’arrière de votre Apple.</p><p>Au vu des éléments cités ci-dessus le devis No XXXXXX est maintenu.</p><p>Nous restons à votre entière disposition pour toute question ou complément d’information.</p><p>Dans l’attente de votre réponse au devis, nous vous prions de recevoir, Monsieur Vedovini, nous meilleurs salutations.</p></blockquote><p>Chose à laquelle j&#8217;ai immédiatement répondu en réaffirmant ma position et en indiquant que je comptai me renseigner rapidement, auprès de la <a href="http://www.frc.ch">Fédération Romande des Consommateurs</a> ainsi que ma protection juridique, sur les recours légaux à ma disposition. Chose que j&#8217;ai faite ce matin.</p><p>En substance, et pour l&#8217;instant, il faut juste commencer à s&#8217;échanger des courriers papier afin d&#8217;établir les choses. Étrangement, envoyer des insultes par e-mail peut vous faire condamner mais il semblerait qu&#8217;en dehors de ça, ça n&#8217;a pas beaucoup de valeur juridique.</p><p>Alors il m&#8217;a semblé que dans le monde numérique où nous vivons maintenant, raconter tout cela (et la future suite) pourrait avoir plusieurs vertus:</p><ul><li>Premièrement, ça me soulage. Étant quelqu&#8217;un d&#8217;extrêmement analytique, qu&#8217;on refuse l&#8217;évidence me fait peter les plombs. Un peu comme si après avoir programmé toute l&#8217;arithmétique dans votre calculatrice, la dernière règle consisterai à lui dire &#8220;1==2&#8243;. Ces trucs là, moi, ça m&#8217;empêche de dormir.</li><li>Ensuite, on ne sait jamais, cela pourrait constituer un point  de pression sur la FNAC. Surtout si suffisamment de monde commence à poster des commentaires d&#8217;encouragement (si vous voyez ce que je veux dire ;)</li><li>Et bien sûr, ça a la vertu de l&#8217;expérience partagée. La prochaine fois que vous emmenez un appareil d&#8217;un certain prix dans un SAV, profitez que votre téléphone fasse des films (au pire des photos) pour filmer votre appareil sous toutes les coutures, le type du SAV et lui faire dire face caméra son nom, la date et que, non, votre appareil n&#8217;est pas passé sous un camion.</li><li>Si vous avez eu des expériences similaires, à la FNAC, chez un revendeur Apple, ou ailleurs dans la région Lausannoise, ça nous donne un forum pour les partager.</li><li>Il se peut également que cela rappel aux jeunes qui nous regarde que même encore maintenant, poster des status sur Facebook ne suffit pas à prouver sa bonne fois.</li></ul><p>Sur ce, merci d&#8217;avoir lu jusque là, n&#8217;hésitez pas à me plaindre, ça me fera plaisir :)</p><p>UPDATE (2010-02-05): Ce matin, petit coup de fil du directeur du magasin de Lausanne, très sympa. On s&#8217;occupe de mon cas.</p><p>UPDATE (2010-02-12): Il a fallu que j&#8217;appelle moi-même le SAV mais j&#8217;ai enfin des nouvelles &#8211; La FNAC me rembourse mon Mac, en bon d&#8217;achat FNAC, et je dois payer si je veux qu&#8217;on me transfert mes données&#8230;</p><h3  class="related_post_title">Most Commented Posts</h3><ul class="related_post"><li><a href="http://vedovini.net/2010/02/sevices-apres-vente/" title="Sévices Après Vente">Sévices Après Vente</a></li><li><a href="http://vedovini.net/2009/08/jmeter-distributed-testing-with-amazon-ec2/" title="JMeter distributed testing with Amazon EC2">JMeter distributed testing with Amazon EC2</a></li><li><a href="http://vedovini.net/2008/09/google-please-no/" title="Google, please, NO!">Google, please, NO!</a></li></ul><div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/cvedovini/blog?a=99Ir9JPxWBk:v06-8F22zZk:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/cvedovini/blog?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/cvedovini/blog?a=99Ir9JPxWBk:v06-8F22zZk:F7zBnMyn0Lo"><img src="http://feeds.feedburner.com/~ff/cvedovini/blog?i=99Ir9JPxWBk:v06-8F22zZk:F7zBnMyn0Lo" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/cvedovini/blog?a=99Ir9JPxWBk:v06-8F22zZk:V_sGLiPBpWU"><img src="http://feeds.feedburner.com/~ff/cvedovini/blog?i=99Ir9JPxWBk:v06-8F22zZk:V_sGLiPBpWU" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/cvedovini/blog?a=99Ir9JPxWBk:v06-8F22zZk:qj6IDK7rITs"><img src="http://feeds.feedburner.com/~ff/cvedovini/blog?d=qj6IDK7rITs" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/cvedovini/blog?a=99Ir9JPxWBk:v06-8F22zZk:gIN9vFwOqvQ"><img src="http://feeds.feedburner.com/~ff/cvedovini/blog?i=99Ir9JPxWBk:v06-8F22zZk:gIN9vFwOqvQ" border="0"></img></a>
</div>]]></content:encoded> <wfw:commentRss>http://vedovini.net/2010/02/sevices-apres-vente/feed/</wfw:commentRss> <slash:comments>12</slash:comments> <feedburner:origLink>http://vedovini.net/2010/02/sevices-apres-vente/</feedburner:origLink></item> <item><title>Experiencing viral growth</title><link>http://feedproxy.google.com/~r/cvedovini/blog/~3/ai1gEfWwmiQ/</link> <comments>http://vedovini.net/2010/01/experiencing-viral-growth/#comments</comments> <pubDate>Sat, 30 Jan 2010 12:15:20 +0000</pubDate> <dc:creator>Claude</dc:creator> <category><![CDATA[marketing]]></category> <category><![CDATA[networking]]></category> <category><![CDATA[portfolio]]></category> <category><![CDATA[books]]></category> <category><![CDATA[facebook]]></category> <category><![CDATA[librarything]]></category> <category><![CDATA[users]]></category> <category><![CDATA[viral growth]]></category><guid isPermaLink="false">http://vedovini.net/?p=507</guid> <description><![CDATA[This is something to hear and talk about it but this is something totally different to experience it, it&#8217;s thrilling, even on modest scales. Since my LibraryThing application for Facebook is out it has clearly had a viral growth curve. So far there are only 435 users and every week I am looking for an [...]]]></description> <content:encoded><![CDATA[<p><a href="http://static.vedovini.net/blog/wp-content/uploads/2010/01/fbLibraryThing_growth.png"><img class="alignright size-medium wp-image-508" title="Number of fbLibraryThing users per week" src="http://static.vedovini.net/blog/wp-content/uploads/2010/01/fbLibraryThing_growth-300x213.png" alt="" width="300" height="213" /></a><strong>This is something to hear and talk about it but this is something totally different to experience it, it&#8217;s thrilling, even on modest scales.</strong></p><p>Since my <a href="http://www.facebook.com/fbLibraryThing">LibraryThing application for Facebook</a> is out it has clearly had a viral growth curve. So far there are only 435 users and every week I am looking for an inflection of this tendency. I know there will be one because there is a limited number of <a href="http://www.librarything.com/">LibraryThing</a> users on Facebook. My goal, right now, is to attract as many of them as possible on this application.</p><p>The next step will be to attract Facebook users to LibraryThing. But I know that for this I will need help from <a href="http://twitter.com/Librarythingtim">Tim Spalding</a> and the LibraryThing team. I have always been grateful for their work but I must admit that I have been quite disappointed recently as I was trying to contact them and they constantly ignored me.</p><p>I am also thinking about open-sourcing the application, because I think it is both a good use case for people who are developing Python/Django applications on Google AppEngine and those who are developing for the Facebook platform. I still have to choose a license but the <a href="http://www.gnu.org/licenses/agpl-3.0.html">GNU Affero General Public License</a> seems like a good match.</p><p>Anyway, if you love books, got plenty of them and want to share your readings, do not forget to give <a href="http://www.librarything.com/">LibraryThing</a> a try and once your are convinced, join the <a href="http://www.facebook.com/fbLibraryThing">Facebook application</a>, with this application you can:</p><ul><li> Add a tab and a box to your profile, listing your most recent books</li><li>Choose the number of books to display in your profile tab</li><li>Choose whether you want to display them with covers only or as a list  which will include your ratings and reviews</li><li>If you grant the application the right to publish to your stream it  will publish books you add to LibraryThing on your wall</li><li>It will also publish reviews as you write them on LibraryThing</li></ul><p>You can also:</p><ul><li>Browse your Facebook friend&#8217;s books</li><li>Find books on the search page</li><li>Share a book you like or comment on it (those are Facebook only  features and will not appear in LibraryThing)</li><li>Add a book to your LibraryThing collection with a single click</li></ul><p>Enjoy :)</p><h3  class="related_post_title">Related posts: (automatically generated)</h3><ul class="related_post"><li><a href="http://vedovini.net/2009/12/a-year-in-review/" title="A year in review">A year in review</a></li><li><a href="http://vedovini.net/2010/07/facebook-pages-notifications/" title="Facebook Pages Notifications">Facebook Pages Notifications</a></li><li><a href="http://vedovini.net/2009/03/vedovininet-is-on-facebook/" title="vedovini.net is on Facebook">vedovini.net is on Facebook</a></li></ul><div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/cvedovini/blog?a=ai1gEfWwmiQ:mzx_ndVhfhk:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/cvedovini/blog?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/cvedovini/blog?a=ai1gEfWwmiQ:mzx_ndVhfhk:F7zBnMyn0Lo"><img src="http://feeds.feedburner.com/~ff/cvedovini/blog?i=ai1gEfWwmiQ:mzx_ndVhfhk:F7zBnMyn0Lo" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/cvedovini/blog?a=ai1gEfWwmiQ:mzx_ndVhfhk:V_sGLiPBpWU"><img src="http://feeds.feedburner.com/~ff/cvedovini/blog?i=ai1gEfWwmiQ:mzx_ndVhfhk:V_sGLiPBpWU" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/cvedovini/blog?a=ai1gEfWwmiQ:mzx_ndVhfhk:qj6IDK7rITs"><img src="http://feeds.feedburner.com/~ff/cvedovini/blog?d=qj6IDK7rITs" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/cvedovini/blog?a=ai1gEfWwmiQ:mzx_ndVhfhk:gIN9vFwOqvQ"><img src="http://feeds.feedburner.com/~ff/cvedovini/blog?i=ai1gEfWwmiQ:mzx_ndVhfhk:gIN9vFwOqvQ" border="0"></img></a>
</div>]]></content:encoded> <wfw:commentRss>http://vedovini.net/2010/01/experiencing-viral-growth/feed/</wfw:commentRss> <slash:comments>1</slash:comments> <feedburner:origLink>http://vedovini.net/2010/01/experiencing-viral-growth/</feedburner:origLink></item> <item><title>A year in review</title><link>http://feedproxy.google.com/~r/cvedovini/blog/~3/xF_IBHRGaWQ/</link> <comments>http://vedovini.net/2009/12/a-year-in-review/#comments</comments> <pubDate>Tue, 29 Dec 2009 00:40:41 +0000</pubDate> <dc:creator>Claude</dc:creator> <category><![CDATA[random]]></category> <category><![CDATA[2009]]></category> <category><![CDATA[amazon]]></category> <category><![CDATA[appengine]]></category> <category><![CDATA[aws]]></category> <category><![CDATA[babelizr]]></category> <category><![CDATA[dita-op]]></category> <category><![CDATA[django]]></category> <category><![CDATA[drupal]]></category> <category><![CDATA[facebook]]></category> <category><![CDATA[fontself]]></category> <category><![CDATA[librarything]]></category> <category><![CDATA[longimanus]]></category> <category><![CDATA[nouvo]]></category> <category><![CDATA[peru]]></category> <category><![CDATA[python]]></category> <category><![CDATA[sharks]]></category> <category><![CDATA[sidewikirss]]></category><guid isPermaLink="false">http://vedovini.net/?p=479</guid> <description><![CDATA[As this year in coming to an end I though I should do a post-mortem, like at the end of a project, to see what went well and what did not. I left the office I was renting downtown and started working from home: It was a good move from work perspective, being alone at [...]]]></description> <content:encoded><![CDATA[<p><a title="Swimming with sharks" href="http://www.flickr.com/photos/cvedovini/3594026972/"><img class="alignright" src="http://farm4.static.flickr.com/3332/3594026972_da146a7cca_m.jpg" alt="" width="240" height="180" /></a>As this year in coming to an end I though I should do a post-mortem, like at the end of a project, to see what went well and what did not.</p><ul><li><strong>I left the office I was renting downtown and started working from home: </strong>It was a good move from work perspective, being alone at home allows me to be really productive. However, as the second part of the year was getting busier it became difficult to put limits and my work/life balance suffered.</li><li><strong>I worked the map editor of the <a href="http://www.dita-op.org/">DITA-OP</a> but did not finish it:</strong> Not good at all, I have not been able to do a release this year. The other problem with the DITA-OP is that I don&#8217;t know my users. I know they are here, somewhere and I really need to find a way to gather the community.</li><li><strong>I started two toys projects, <a href="http://vedovini.net/2009/09/sidewiki-rss/">SidewikiRSS.com</a> and a <a href="http://www.facebook.com/apps/application.php?id=159924979291">Facebook application for LibraryThing</a>:</strong> SidewikiRSS.com is rolling on its own, it does not cost me anything beside the domain name (thanks Google App Engine), it&#8217;s used regularly and bring some traffic here. fbLibraryThing is slowly but steadily growing but I am wondering if I will be able to add new features &#8211; I am completely dependent on the LibraryThing API and I will need help from the <a href="http://www.librarything.com">LibraryThing</a> team if I want to go farther.</li><li><strong>I completely put aside my super-secret Babelizr project:</strong> That&#8217;s not a good thing, for sure, but at least it was because of too much paid work. A positive thing is that I greatly improved my <a href="http://python.org/">Python</a> and <a href="http://www.djangoproject.com/">Django</a> skills with other projects and it will payoff for Babelizr.</li><li><strong>I can now consider myself an <a href="http://aws.amazon.com/">Amazon Web Services</a> and <a href="http://code.google.com/appengine/">Google App Engine</a> expert:</strong> And that&#8217;s a tremendous addition to my curriculum. I need now to dedicate more time to their respective communities.</li><li><strong>I accepted too many projects in the second part of the year:</strong> The beginning of the year had been slow and I though I needed as many contacts as possible to build a sustainable business. Overall this is a good thing &#8211; especially since I exceeded my financial goals. The other positive side is that I only accepted interesting projects and that I met really nice people. But I really had a lot of pressure in the last quarter and this was definitely not the purpose of being a freelancer &#8211; &#8220;Working more to earn more&#8221; is not my moto.</li><li><strong>I did not blogged enough:</strong> Especially since I gained a lot of experience in many fields and with many tools, I should have definitely written more about these.</li></ul><p>And last, but not least:</p><ul><li><strong>I swam with sharks:</strong> Biggest thrill ever! I swam with two <a href="http://en.wikipedia.org/wiki/Oceanic_whitetip_shark">Oceanic Whitetip (Carcharhinus longimanus)</a> in the <a href="http://www.flickr.com/photos/cvedovini/sets/72157619127143011/">Red Sea</a>. My only regret is that I have been totally unable to take a descent picture or make a video of this event.</li><li><strong>I skied almost every week-end of the winter season and hiked almost every week-end of the summer season:</strong> This prepared me really well for <a href="http://www.flickr.com/photos/cvedovini/sets/72157622490260992/">our 2 weeks vacation in Peru</a>.</li><li><strong>I have been more than 80 times to the movie theater:</strong> Thanks to the <a href="http://www.pathelausanne.ch/custom/passpathe">Pathé Pass</a> Yang offered me last Christmas. It allowed me to see movies (good and bad) that I would not have seen otherwise.</li></ul><p>I think I can say it was a good year, tiring, a bit stressful near the end but a good year. However, I must say it did not bring me any closer to my biggest goal that is to find ways to automate my revenue stream, so I really need to work that out next year.</p><p>The other planned features of next year are:</p><ul><li><strong>Releasing the latest version of the DITA-OP</strong> and finding a way to build and animate the community.</li><li><strong>More blogging</strong> (like everyblogger else) and tweeting. Find a better organization of my Facebook presence.</li><li><strong>Connecting with the LibraryThing team</strong>, although this proved to be difficult so far.</li><li><strong>Coming back to Babelizr</strong>, may be starting with building external interest around the project first in order to force commitment.</li><li><strong>Dedicating more time to online communities:</strong> Google App Engine, AWS, Drupal, Django, etc. May be through <a href="http://stackoverflow.com/">Stack Overflow</a>.</li><li><strong>Planning of a 4 weeks vacation</strong> dedicated to hiking or diving.</li><li><strong>Watch as many movies as possible</strong> with my renewed Pathé Pass.</li></ul><p>And, of course, keeping my clients happy :)</p><p>I only worked for two public projects this year (others are either private or still in stealth mode, so I cannot talk about them):</p><ul><li><a href="http://vedovini.net/2009/10/my-fontself-is-better-than-your-font/">Fontself</a>, a startup company which provides a revolutionary new experience of text, through digital text personalization. It provides digital fonts that preserves the gestures of a given handwriting and the original look of the drawing appliance (ball-point pen, pencil, ink, paper, etc.). I participated in the design of the font distribution system and its implementation on the <a href="http://aws.amazon.com/">Amazon&#8217;s cloud infrastructure</a> using <a href="http://python.org/">Python</a> and <a href="http://www.djangoproject.com/">Django</a>.</li><li><a href="http://www.nouvo.ch/">nouvo.ch</a>, the multimedia magazine from the Swiss Romand Television channel asked me to redevelop their website using the <a href="http://drupal.org/">Drupal CMS</a> and various media management modules.</li></ul><h3  class="related_post_title">Related posts: (automatically generated)</h3><ul class="related_post"><li><a href="http://vedovini.net/2010/06/how-to-manage-google-appengine-maintenance-periods/" title="How to manage Google AppEngine maintenance periods">How to manage Google AppEngine maintenance periods</a></li><li><a href="http://vedovini.net/2010/06/properly-uploading-files-to-amazon-s3/" title="Properly uploading files to Amazon S3">Properly uploading files to Amazon S3</a></li><li><a href="http://vedovini.net/2010/01/experiencing-viral-growth/" title="Experiencing viral growth">Experiencing viral growth</a></li></ul><div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/cvedovini/blog?a=xF_IBHRGaWQ:rudpcc7LUpM:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/cvedovini/blog?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/cvedovini/blog?a=xF_IBHRGaWQ:rudpcc7LUpM:F7zBnMyn0Lo"><img src="http://feeds.feedburner.com/~ff/cvedovini/blog?i=xF_IBHRGaWQ:rudpcc7LUpM:F7zBnMyn0Lo" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/cvedovini/blog?a=xF_IBHRGaWQ:rudpcc7LUpM:V_sGLiPBpWU"><img src="http://feeds.feedburner.com/~ff/cvedovini/blog?i=xF_IBHRGaWQ:rudpcc7LUpM:V_sGLiPBpWU" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/cvedovini/blog?a=xF_IBHRGaWQ:rudpcc7LUpM:qj6IDK7rITs"><img src="http://feeds.feedburner.com/~ff/cvedovini/blog?d=qj6IDK7rITs" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/cvedovini/blog?a=xF_IBHRGaWQ:rudpcc7LUpM:gIN9vFwOqvQ"><img src="http://feeds.feedburner.com/~ff/cvedovini/blog?i=xF_IBHRGaWQ:rudpcc7LUpM:gIN9vFwOqvQ" border="0"></img></a>
</div>]]></content:encoded> <wfw:commentRss>http://vedovini.net/2009/12/a-year-in-review/feed/</wfw:commentRss> <slash:comments>0</slash:comments> <feedburner:origLink>http://vedovini.net/2009/12/a-year-in-review/</feedburner:origLink></item> </channel> </rss><!-- Dynamic page generated in 1.294 seconds. --><!-- Cached page generated by WP-Super-Cache on 2012-02-07 11:52:28 --><!-- Compression = gzip -->

