<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
 
 <title>Igor Sobreira</title>
 <link href="http://igorsobreira.com/atom.xml" rel="self"/>
 <link href="http://igorsobreira.com/"/>
 <updated>2013-03-17T18:20:17-10:00</updated>
 <id>http://igorsobreira.com/</id>
 <author>
   <name>Igor Sobreira</name>
   <email>igor@igorsobreira.com</email>
 </author>

 
 <entry>
   <title>Testing infinite loops</title>
   <link href="http://igorsobreira.com/2013/03/17/testing-infinite-loops.html"/>
   <updated>2013-03-17T00:00:00-10:00</updated>
   <id>http://igorsobreira.com/2013/03/17/testing-infinite-loops</id>
   <content type="html">&lt;p&gt;Yesterday I was working on a script that should run forever, or at least until the user stops it. The library behind it was already tested except for this little function:&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;python&quot;&gt;&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;collect&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;directory&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;sequential&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Sequential&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;directory&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;live&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Live&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;directory&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;while&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;live&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;process&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;sequential&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;process&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;this is the entry point of my library. I have an executable that just parses a directory name from command line and call this function. It's purpose it to collect all files from a directory, filter based on some rules, and publish the file names in a queue which will be consumed by another script. It runs forever because newly created files are detected and collected too.&lt;/p&gt;

&lt;p&gt;Anyway, what it does doesn't really matter, the problem is: how to test this function since it's supposed to run forever?&lt;/p&gt;

&lt;p&gt;I don't mind to have just unit tests for this function because I already have more integration-like tests for the classes it uses. The first solution I thought was something like this:&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;python&quot;&gt;&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;collect&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;directory&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;sequential&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Sequential&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;directory&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;live&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Live&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;directory&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;while&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;should_continue&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;():&lt;/span&gt;  &lt;span class=&quot;c&quot;&gt;# new function to mock on tests: UGLY!&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;live&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;process&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;sequential&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;process&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;should_continue&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;():&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;True&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;this way I could mock &lt;code&gt;should_continue()&lt;/code&gt; in my test and make it return &lt;code&gt;False&lt;/code&gt; to abort the loop when I want. That works but it's ugly! &lt;strong&gt;I don't like to add dependency injections only for tests&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;I asked on #python on irc and marienz gave a neat idea: raise an exception.
I could mock &lt;code&gt;live.process()&lt;/code&gt; and &lt;code&gt;sequential.process()&lt;/code&gt; and raise an exception, this way I know they were called as I expected and also it will also abort the loop!&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;python&quot;&gt;&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;pytest&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;mock&lt;/span&gt;

&lt;span class=&quot;c&quot;&gt;# this is the library under test&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;collectors&lt;/span&gt;

&lt;span class=&quot;c&quot;&gt;# replace original classed with mock objects&lt;/span&gt;
&lt;span class=&quot;nd&quot;&gt;@mock.patch&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;#39;collectors.Sequential&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;nd&quot;&gt;@mock.patch&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;#39;collectors.Live&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;test_collect_should_loop_forever_processing_both_collectors&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;collectors_Live&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;collectors_Sequential&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;

    &lt;span class=&quot;c&quot;&gt;# build mock instances. process() method will raise error&lt;/span&gt;
    &lt;span class=&quot;c&quot;&gt;# when called for the 2nd time. The code for `ErrorAfter`&lt;/span&gt;
    &lt;span class=&quot;c&quot;&gt;# is bellow&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;seq&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;mock&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Mock&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;([&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;#39;process&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;seq&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;process&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;side_effect&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ErrorAfter&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;live&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;mock&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Mock&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;([&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;#39;process&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;live&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;process&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;side_effect&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ErrorAfter&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

    &lt;span class=&quot;c&quot;&gt;# ensure mocked classes builds my mocked instances&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;collectors_Sequential&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;return_value&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;seq&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;collectors_Live&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;return_value&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;live&lt;/span&gt;

    &lt;span class=&quot;c&quot;&gt;# `ErrorAfter` will raise `CallableExhausted`&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;with&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;pytest&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;raises&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;CallableExhausted&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;collectors&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;collect&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;#39;/tmp/files&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    
    &lt;span class=&quot;c&quot;&gt;# make sure our classed are instantiated with directory&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;collectors_Sequential&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;assert_called_once_with&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;#39;/tmp/files&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;collectors_Live&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;assert_called_once_with&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;#39;/tmp/files&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;This test uses &lt;a href=&quot;http://pytest.org/&quot;&gt;py.test&lt;/a&gt; and &lt;a href=&quot;http://www.voidspace.org.uk/python/mock/&quot;&gt;mock&lt;/a&gt;. I hope the comments explains enough. The idea is simple: make &lt;code&gt;process()&lt;/code&gt; raise an Exception to abort the loop.
The &lt;code&gt;ErrorAfter&lt;/code&gt; class is a small helper, it builds a callable object that will raise a specific exception after &lt;code&gt;n&lt;/code&gt; calls. I created a custom exception here to make sure my test fails if any other exception is raised. See the code bellow.&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;python&quot;&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;ErrorAfter&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;object&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
    &lt;span class=&quot;sd&quot;&gt;&amp;#39;&amp;#39;&amp;#39;&lt;/span&gt;
&lt;span class=&quot;sd&quot;&gt;    Callable that will raise `CallableExhausted`&lt;/span&gt;
&lt;span class=&quot;sd&quot;&gt;    exception after `limit` calls&lt;/span&gt;

&lt;span class=&quot;sd&quot;&gt;    &amp;#39;&amp;#39;&amp;#39;&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;__init__&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;limit&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
        &lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;limit&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;limit&lt;/span&gt;
        &lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;calls&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;__call__&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
        &lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;calls&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;calls&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;limit&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;raise&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;CallableExhausted&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;CallableExhausted&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;ne&quot;&gt;Exception&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;pass&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;h3&gt;Conclusion&lt;/h3&gt;

&lt;p&gt;Try to avoid as much as possible to create dependency injections specifically for your tests. In dynamic languages like Python it's very easy to replace a specific component with a mock object without adding extra complexity to your code just to allow unit testing.&lt;/p&gt;

&lt;p&gt;This was the first time I had to test a infinite loop, it's possible and easy!&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Start simple</title>
   <link href="http://igorsobreira.com/2013/01/03/start-simple.html"/>
   <updated>2013-01-03T00:00:00-10:00</updated>
   <id>http://igorsobreira.com/2013/01/03/start-simple</id>
   <content type="html">&lt;p&gt;Last week I wrote a &lt;a href=&quot;http://www.igorsobreira.com/2012/12/31/unnecessary-classes.html&quot;&gt;post about unnecessary classes&lt;/a&gt;, and that kept me thinking about how common people write classes or more complex designs upfront just because it would be easier to evolve and extend later.&lt;/p&gt;

&lt;p&gt;One suggestion I gave was to use a dictionary instead of a class which had no methods but the constructor. This class was just holding state, data, so a dictionary is enough. Let's start simple...&lt;/p&gt;

&lt;p&gt;I'll stick with this example because it's real code, even if it's purpose is not 100% clear:&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;python&quot;&gt;&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;create_button_link&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;matchobject&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;line&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;button_link&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;matchobject&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;groupdict&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;button_link&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;update&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;({&lt;/span&gt;
        &lt;span class=&quot;s&quot;&gt;&amp;#39;name&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;matchobject&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;group&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt;
        &lt;span class=&quot;s&quot;&gt;&amp;#39;size&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;int&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;button_link&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;#39;size&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]),&lt;/span&gt;
        &lt;span class=&quot;s&quot;&gt;&amp;#39;colors&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;button_link&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;#39;colors&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;][&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:]&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;split&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;.&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt;
        &lt;span class=&quot;s&quot;&gt;&amp;#39;line&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;line&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;button_link&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;this function returns a dictionary with many properties of a button, ok. But now I need to increase its size, I could write a function like:&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;python&quot;&gt;&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;increase_button_link_size&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;button_link&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;pixels&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;button_link&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;#39;size&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;pixels&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;button_link&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;At some point you may want to change the design and make a &lt;code&gt;ButtonLink&lt;/code&gt; class, maybe because you need a much more complex model and OO could help. Anyway, here is how the class could be implemented:&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;python&quot;&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;ButtonLink&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;object&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;__init__&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;matchobject&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;line&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
      &lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;__dict__&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;matchobject&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;groupdict&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
      &lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;name&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;matchobject&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;group&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;size&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;int&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;size&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;colors&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;colors&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:]&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;split&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;.&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;line&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;line&lt;/span&gt;
      
    &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;increase&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;pixels&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
        &lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;size&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;pixels&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;the problem now is that &lt;code&gt;button_link&lt;/code&gt;s are being used as dictionaries all over the place, like &lt;code&gt;button_link['size']&lt;/code&gt;. And even worse, this could be a public API and you may not have access to the clients using it. In this case we could simulate the dict api implementing &lt;code&gt;__getitem__&lt;/code&gt;:&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;python&quot;&gt;&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;warnings&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;ButtonLink&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;object&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
    &lt;span class=&quot;c&quot;&gt;# ... same as above&lt;/span&gt;
    
    &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;__getitem__&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;item&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;warnings&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;warn&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;Dict-like access is deprecated, please use `.{0}`&amp;quot;&lt;/span&gt;
                      &lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;format&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;item&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt; &lt;span class=&quot;ne&quot;&gt;DeprecationWarning&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;getattr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;item&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;Now you can use &lt;code&gt;button_link.size&lt;/code&gt; and &lt;code&gt;button_link['size']&lt;/code&gt;. And I also added a deprecation warning to notify the users that they should use the object API from now on.
And you should also modify the functions above to create and manipulate the object instead of the dictionary, also raising warnings if you want.&lt;/p&gt;

&lt;p&gt;You may want to implement other dictionary methods, like &lt;code&gt;keys&lt;/code&gt;, &lt;code&gt;items&lt;/code&gt;, &lt;code&gt;has_key&lt;/code&gt;, &lt;code&gt;__contains__&lt;/code&gt;, etc.&lt;/p&gt;

&lt;h3&gt;Why not make a dict subclass?&lt;/h3&gt;

&lt;p&gt;The main reason I wouldn't subclass &lt;code&gt;dict&lt;/code&gt; in this case is philosophical: &lt;code&gt;ButtonLink&lt;/code&gt; should behave like a &lt;code&gt;dict&lt;/code&gt; (temporarily), but it is not a dictionary. A good example of a &lt;code&gt;dict&lt;/code&gt; subclass is &lt;a href=&quot;http://hg.python.org/cpython/file/tip/Lib/collections.py&quot;&gt;&lt;code&gt;OrderedDict&lt;/code&gt;&lt;/a&gt;, it is a dictionary with customized behavior.&lt;/p&gt;

&lt;p&gt;Another aspect to keep in mind is when we write a subclass is that we inherit all the methods from the superclass, all the API, and it's now part of my class API. In my case I don't want to implement the &lt;code&gt;__setitem__&lt;/code&gt; method, because the clients should not be using it, all the time you need to modify the &lt;code&gt;button_link&lt;/code&gt; dict there is a specialized function to do so, and these functions I can easily rewrite to use the object API.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;&quot;What about &lt;code&gt;isinstance()&lt;/code&gt;?!&quot;&lt;/em&gt;. Yeah, you're going to loose it, since &lt;code&gt;button_link&lt;/code&gt; is not a &lt;code&gt;dict&lt;/code&gt; anymore &lt;code&gt;isinstance(button_link, dict)&lt;/code&gt; is False. But I believe you should not be using it, type checking with &lt;code&gt;isinstance()&lt;/code&gt; and even worse, &lt;code&gt;type()&lt;/code&gt;, is not very common on languages like python. &quot;If it walks like a duck and quacks like a duck, then it is a duck&quot;! I know that sometimes &lt;code&gt;isinstance()&lt;/code&gt; is handy, but I don't think it's appropriate here because of the philosophical argument I gave above.&lt;/p&gt;

&lt;h3&gt;Conclusion&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Start simple, it's always easier to evolve to a more complex design than the other way around&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Using Python &lt;a href=&quot;http://www.rafekettler.com/magicmethods.html&quot;&gt;magic methods&lt;/a&gt; your objects can easily look like a native data structure, so start using simple data structures and write your own if you need later. Another language feature that helps this incremental design evolution is &lt;a href=&quot;http://docs.python.org/2/library/functions.html#property&quot;&gt;properties&lt;/a&gt;, a simple attribute can evolve to a complex getter/setter transparently.&lt;/p&gt;

&lt;p&gt;Don't forget the Zen of Python:&lt;/p&gt;

&lt;blockquote&gt;&lt;p&gt;Simple is better than complex.
Complex is better than complicated.&lt;/p&gt;&lt;/blockquote&gt;
</content>
 </entry>
 
 <entry>
   <title>Unnecessary classes</title>
   <link href="http://igorsobreira.com/2012/12/31/unnecessary-classes.html"/>
   <updated>2012-12-31T00:00:00-10:00</updated>
   <id>http://igorsobreira.com/2012/12/31/unnecessary-classes</id>
   <content type="html">&lt;p&gt;Today I opened a python module that made me feel sad. It has two classes: one of them has 4 methods, all of them static, and no attributes; the other has only one method: &lt;code&gt;__init__&lt;/code&gt;, and 5 attributes.&lt;/p&gt;

&lt;p&gt;Why people still write classes like these?&lt;/p&gt;

&lt;h2&gt;Use functions&lt;/h2&gt;

&lt;p&gt;...instead of classes with just static methods. If you have this class just to group the functions in a common namespace then create a new module (.py file), this is how python organize namespaces, and it's good, use it!&lt;/p&gt;

&lt;p&gt;Here is the first class I saw today&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;python&quot;&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Buttonate&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;object&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;

    &lt;span class=&quot;nd&quot;&gt;@staticmethod&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;find_files&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;quiet&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;False&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
        &lt;span class=&quot;c&quot;&gt;# ...&lt;/span&gt;
    
    &lt;span class=&quot;nd&quot;&gt;@staticmethod&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;find_links&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;files&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
        &lt;span class=&quot;c&quot;&gt;# ...&lt;/span&gt;
    
    &lt;span class=&quot;nd&quot;&gt;@staticmethod&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;buttonate&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;buttons&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;overwrite&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;False&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;quiet&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;False&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
        &lt;span class=&quot;c&quot;&gt;# ...&lt;/span&gt;

    &lt;span class=&quot;nd&quot;&gt;@staticmethod&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;link_parser&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;file&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
        &lt;span class=&quot;c&quot;&gt;# ...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;and here is how I would rewrite it:&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;python&quot;&gt;&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;buttonate_find_files&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;quiet&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;False&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
    &lt;span class=&quot;c&quot;&gt;# ...&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;buttonate_find_links&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;files&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
    &lt;span class=&quot;c&quot;&gt;# ...&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;buttonate_buttonate&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;buttons&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;overwrite&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;False&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;quiet&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;False&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
    &lt;span class=&quot;c&quot;&gt;# ...&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;buttonate_link_parser&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;file&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
    &lt;span class=&quot;c&quot;&gt;# ...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;I usually just start creating the functions I need, and if I get to this point where I have multiple functions doing related work I just create a module and move them there:&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;python&quot;&gt;&lt;span class=&quot;c&quot;&gt;# new file: buttonate.py&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;find_files&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;quiet&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;False&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
    &lt;span class=&quot;c&quot;&gt;# ...&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;find_links&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;files&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
    &lt;span class=&quot;c&quot;&gt;# ...&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;buttonate&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;buttons&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;overwrite&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;False&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;quiet&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;False&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
    &lt;span class=&quot;c&quot;&gt;# ...&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;link_parser&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;file&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
    &lt;span class=&quot;c&quot;&gt;# ...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;h2&gt;Use builtin data structures&lt;/h2&gt;

&lt;p&gt;...instead of &lt;em&gt;attributes-only-classes&lt;/em&gt;. Here is the other class I saw today:&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;python&quot;&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;ButtonLink&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;object&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;__init__&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;matchobject&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;l&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
      &lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;__dict__&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;matchobject&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;groupdict&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
      &lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;name&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;matchobject&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;group&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;size&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;int&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;size&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;colors&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;colors&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:]&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;split&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;.&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;line&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;l&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;This is a class being used similar to a struct in C. We could use a dictionary here, and a factory function doing the work &lt;code&gt;__init__&lt;/code&gt; is doing in this example:&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;python&quot;&gt;&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;create_button_link&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;matchobject&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;line&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;button_link&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;matchobject&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;groupdict&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;button_link&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;update&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;({&lt;/span&gt;
        &lt;span class=&quot;s&quot;&gt;&amp;#39;name&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;matchobject&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;group&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt;
        &lt;span class=&quot;s&quot;&gt;&amp;#39;size&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;int&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;button_link&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;#39;size&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]),&lt;/span&gt;
        &lt;span class=&quot;s&quot;&gt;&amp;#39;colors&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;button_link&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;#39;colors&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;][&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:]&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;split&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;.&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt;
        &lt;span class=&quot;s&quot;&gt;&amp;#39;line&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;line&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;button_link&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;Dictionaries are fast, &lt;a href=&quot;http://hg.python.org/cpython/file/tip/Objects/dictnotes.txt&quot;&gt;well&lt;/a&gt; &lt;a href=&quot;http://hg.python.org/cpython/file/tip/Objects/dictobject.c&quot;&gt;designed&lt;/a&gt; and are &lt;a href=&quot;http://mail.python.org/pipermail/python-dev/2012-December/123028.html&quot;&gt;always being improved&lt;/a&gt; by smart people.&lt;/p&gt;

&lt;p&gt;Another interesting builtin data structure is &lt;a href=&quot;http://docs.python.org/2/library/collections.html#collections.namedtuple&quot;&gt;namedtuple&lt;/a&gt;. And it has a clever &lt;a href=&quot;http://hg.python.org/cpython/file/tip/Lib/collections.py&quot;&gt;implementation&lt;/a&gt;, you should check it out :)&lt;/p&gt;

&lt;p&gt;One rule I follow when using dictionaries like the example above is to always modify them with specialized functions. You'll end up with well defined structures and modules that know how to build and manage these structures inside your application.&lt;/p&gt;

&lt;p&gt;What I'm suggesting here is actually the opposite of OO, instead of writing a class with state and methods, keep the state on dictionaries (or tuples, lists, sets) and write functions to manipulate the state. I've been using this approach much more that classes lately.&lt;/p&gt;

&lt;h2&gt;References&lt;/h2&gt;

&lt;p&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=o9pEzgHorH0&quot;&gt;Stop writing classes&lt;/a&gt; is a great talk by Jack Diederich at PyCon 2012, showing examples where classes are overused.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Python coverage threshold</title>
   <link href="http://igorsobreira.com/2012/11/05/python-coverage-threshold.html"/>
   <updated>2012-11-05T00:00:00-10:00</updated>
   <id>http://igorsobreira.com/2012/11/05/python-coverage-threshold</id>
   <content type="html">&lt;p&gt;Ned Batchelder committed a new feature to coverage.py 2 days ago, it's a way to verify coverage threshold. Basically a way to fail your tests if the coverage is not enough.
For now you need to install from the repository to get the new feature&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;$ pip install hg+https://bitbucket.org/ned/coveragepy#egg=coverage
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This is how to use from the command line:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;$ coverage run run_my_tests.py 
... running all tests
$ coverage report --fail-under=100
... display the report
$ echo $?
2
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;If your coverage is not 100% your exit status will be 2. This will make your CI fail if your coverage is not enough :).
You can also verify coverage using the python API, in this case you need to verify the return value from &lt;code&gt;report()&lt;/code&gt; function, here is an example:&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;python&quot;&gt;&lt;span class=&quot;n&quot;&gt;cov&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;coverage&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;coverage&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;..&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;cov&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;start&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;ret&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;run_all_my_tests&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;cov&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;stop&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ret&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;covered&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;cov&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;report&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;assert&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;covered&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;100&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;quot;Not enough coverage&amp;quot;&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;I've created a decorator to make this easier:&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;python&quot;&gt;&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;ensure_coverage&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;percentage&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;**&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;cov_options&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;decorator&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
        &lt;span class=&quot;nd&quot;&gt;@wraps&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;wrapper&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;args&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;**&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;kw&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;cov&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;coverage&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;coverage&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;branch&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;True&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;**&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;cov_options&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;cov&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;start&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;ret&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;args&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;**&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;kw&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;cov&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;stop&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ret&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
                &lt;span class=&quot;n&quot;&gt;covered&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;cov&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;report&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
                &lt;span class=&quot;k&quot;&gt;assert&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;covered&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;percentage&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; \
                    &lt;span class=&quot;s&quot;&gt;&amp;quot;Not enough coverage: {0:.2f}%. You need at least {1}%&amp;quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;format&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;covered&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;percentage&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ret&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;wrapper&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;decorator&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;This is an usage example for this django app I'm working on:&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;python&quot;&gt;&lt;span class=&quot;nd&quot;&gt;@ensure_coverage&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;99&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;source&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;#39;filecabinet&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;omit&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;#39;filecabinet/tests/*&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;runtests&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;():&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;test_runner&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;get_runner&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;settings&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)()&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;test_runner&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;run_tests&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;([&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;#39;filecabinet&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;__name__&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;#39;__main__&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;sys&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;exit&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;runtests&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;())&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;Here are the related commits, if you're interested:&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://bitbucket.org/ned/coveragepy/changeset/7ea709fc4c1190cf0ffe0aba1a49e6fffe683d2f&quot;&gt;https://bitbucket.org/ned/coveragepy/changeset/7ea709fc4c1190cf0ffe0aba1a49e6fffe683d2f&lt;/a&gt;
&lt;a href=&quot;https://bitbucket.org/ned/coveragepy/changeset/90014f4defd336f05851bdfc01c2b5af60a933c9&quot;&gt;https://bitbucket.org/ned/coveragepy/changeset/90014f4defd336f05851bdfc01c2b5af60a933c9&lt;/a&gt;
&lt;a href=&quot;https://bitbucket.org/ned/coveragepy/changeset/ba7267fe525001dba99ed1c2c9d11f0724ad9950&quot;&gt;https://bitbucket.org/ned/coveragepy/changeset/ba7267fe525001dba99ed1c2c9d11f0724ad9950&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And the discussion on the issue:&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://bitbucket.org/ned/coveragepy/issue/139/easy-check-for-a-certain-coverage-in-tests&quot;&gt;https://bitbucket.org/ned/coveragepy/issue/139/easy-check-for-a-certain-coverage-in-tests&lt;/a&gt;&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Improving performance of Django test suite</title>
   <link href="http://igorsobreira.com/2012/09/19/improving-performance-of-django-test-suite.html"/>
   <updated>2012-09-19T00:00:00-10:00</updated>
   <id>http://igorsobreira.com/2012/09/19/improving-performance-of-django-test-suite</id>
   <content type="html">&lt;p&gt;I'm working on a small django application these days which offers templates to override &lt;a ref=&quot;https://github.com/sehmaschine/django-filebrowser&quot;&gt;django-filebrowser&lt;/a&gt;'s templates to remove the Grappelli dependency.&lt;/p&gt;

&lt;p&gt;It's a small app, consisting 99% of templates. There are only 19 tests which take 35 seconds to execute! All of them performs at least one request using django test client, no selenium, no real HTTP requests, and still 35 seconds!&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/uploads/tests-speed-very-slow.png&quot; alt=&quot;Tests speed very slow&quot; /&gt;&lt;/p&gt;

&lt;p&gt;After a run with &lt;a href=&quot;http://docs.python.org/library/profile.html&quot;&gt;cProfile&lt;/a&gt; I've noticed many calls to hash functions, specifically &lt;code&gt;&lt;a href=&quot;https://github.com/django/django/blob/master/django/utils/crypto.py#L135&quot;&gt;django.utils.crypto.pbkdf2()&lt;/a&gt;&lt;/code&gt; and it's helper &lt;code&gt;_fast_hmac&lt;/code&gt;. Then I came up with this very complex patch to my settings:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;+    PASSWORD_HASHERS = (
+        'django.contrib.auth.hashers.UnsaltedMD5PasswordHasher',   
+    ),
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Now the tests execute on 6 seconds!&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/uploads/tests-speed-improved.png&quot; alt=&quot;Tests speed improved&quot; /&gt;&lt;/p&gt;

&lt;p&gt;You probably want a safer hash function for your user passwords in production, but there is no problem to use a simpler one for tests. This extensible way to deal with password hashers was introduced in Django 1.4, you can &lt;a href=&quot;https://docs.djangoproject.com/en/1.4/topics/auth/#how-django-stores-passwords&quot;&gt;read more about it on the docs.&lt;/a&gt;&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Vagrant plugin to take screenshots</title>
   <link href="http://igorsobreira.com/2012/03/13/vagrant-plugin-to-take-screenshots.html"/>
   <updated>2012-03-13T00:00:00-10:00</updated>
   <id>http://igorsobreira.com/2012/03/13/vagrant-plugin-to-take-screenshots</id>
   <content type="html">&lt;p&gt;I've been using &lt;a href=&quot;http://vagrantup.com&quot;&gt;Vagrant&lt;/a&gt; a lot at work. These days we were facing some problems when our VMs were booting and a friend, &lt;a href=&quot;http://twitter.com/jbochi&quot; title=&quot;Juarez Bochi&quot;&gt;jbochi&lt;/a&gt;, came up with an idea to take a screenshot from a running VM.&lt;/p&gt;

&lt;p&gt;He found this command on &lt;code&gt;VBoxManage&lt;/code&gt;:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;$ VBoxManage controlvm [vm-uuid] screenshotpng [output-filename]
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;And it helped a lot! That's when we had the idea to wrap this command in a script to keep using. Initially I've created a small python script, but then reading about &lt;a href=&quot;http://vagrantup.com/docs/extending/index.html&quot;&gt;vagrant plugins&lt;/a&gt; (&lt;a href=&quot;http://twitter.com/hltbra&quot; title=&quot;Hugo Lopes Tavares&quot;&gt;hltbra&lt;/a&gt;'s suggestion) I've decided to create one.&lt;/p&gt;

&lt;p&gt;The &lt;a href=&quot;http://github.com/igorsobreira/vagrant-screenshot/&quot;&gt;vagrant-screenshot&lt;/a&gt; plugin is very simple. You just need to install &lt;a href=&quot;https://rubygems.org/gems/vagrant-screenshot&quot;&gt;the gem&lt;/a&gt; and use:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;$ gem install vagrant-screenshot
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Here is an usage example:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;$ vagrant screenshot -o
[vagrant] Taking screenshot for default
[vagrant] Screenshot saved on screenshot-default.png
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;By default it takes screenshots for all active VMs. The &lt;code&gt;-o (--open)&lt;/code&gt; option opens the images when done (only works on OS X for now)&lt;/p&gt;

&lt;p&gt;See the help for more details&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;$ vagrant screenshot --help
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;PS.: The problem I've mentioned we were facing ended up in a &lt;a href=&quot;https://github.com/mitchellh/vagrant/pull/771&quot;&gt;pull request to vagrant&lt;/a&gt;, but unfortunately it wasn't accepted :o)&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Book review - Being Geek</title>
   <link href="http://igorsobreira.com/2011/12/28/book-review-being-geek.html"/>
   <updated>2011-12-28T00:00:00-10:00</updated>
   <id>http://igorsobreira.com/2011/12/28/book-review-being-geek</id>
   <content type="html">&lt;p&gt;&lt;img src=&quot;/assets/uploads/being-geek.jpeg&quot; alt=&quot;Book Being Geek&quot; /&gt;&lt;/p&gt;

&lt;p&gt;I've finished reading this book, &lt;a href=&quot;&quot;&gt;Being Geek&lt;/a&gt;, by Michael Lopp, an experienced engineering manager from Silicon Valley. And recommend it...&lt;/p&gt;

&lt;p&gt;It's a book about geeks professionalism, career. I liked the way the author exposes his ideas, he's clear and pragmatic. Right in the second chapter there are these three questions I think it's worth pointing out:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Are you actively defining the technical direction for your product?&lt;/li&gt;
&lt;li&gt;Do you understand what you need to do in order to grow?&lt;/li&gt;
&lt;li&gt;Are you hitting your dates? Are you meeting your commitments? Are you doing what you say you’re going to do?&lt;/li&gt;
&lt;/ul&gt;


&lt;p&gt;That's it! That's what you need to ask yourself every day. Those answers will make you realize if this job is being useful for you to archive your professional goal in your life.&lt;/p&gt;

&lt;p&gt;Later in the book he talks about task management, to-do lists and so on. And a very interesting one he calls &quot;The Trickle List&quot;. This is not a simple to-do list for that day. It's a list of tasks you do every day with a bigger goal in mind, in the future. If you want to be a better engineer, every day you may want to learn something, improve on something, read something. I suddenly realized I was missing this list...&lt;/p&gt;

&lt;p&gt;Well, I liked the book. I was not very excited reading the first chapters. But as I continued reading it just got better and better. The author writes comfortably about our career, being an engineer or a manager. The book is full of good advices based on experience. Hiring process, remote working, giving presentations, etc.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Command line interface to FMS Admin</title>
   <link href="http://igorsobreira.com/2011/12/25/command-line-interface-to-FMS-admin.html"/>
   <updated>2011-12-25T00:00:00-10:00</updated>
   <id>http://igorsobreira.com/2011/12/25/command-line-interface-to-FMS-admin</id>
   <content type="html">&lt;p&gt;I've been working with Flash Media Server for the last 8 months now, and one tool that really annoys me is the Administration Console. I miss a command line interface to accomplish tasks like see all live streams, reload an app, etc.&lt;/p&gt;

&lt;p&gt;That's why I've started the &lt;a href=&quot;https://github.com/igorsobreira/fms-admin-api/&quot;&gt;fms-admin-api&lt;/a&gt;. It's a command line client to &lt;a href=&quot;http://help.adobe.com/en_US/flashmediaserver/adminapi/WSa4cb07693d12388431df580a12a34991ebc-8000.html&quot;&gt;Flash Media Server Administration API&lt;/a&gt;. Since it's written in ruby, it's possible to use the ruby client class directly. Use rubygems to install:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;$ gem install fms-admin-api
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The way it works is really simple. Here is an example: there is a reloadApp() method available that accepts the arguments host, auser, apswd and appInst. The command line interface just replaces from camelCase syntax to underscore:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;$ fmsapi reload_app --host=fms.example.com --auser=fms --apswd=secret --app_inst=live
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;There are &lt;a href=&quot;https://github.com/igorsobreira/fms-admin-api/issues?sort=created&amp;amp;direction=desc&amp;amp;state=open&quot;&gt;improvements&lt;/a&gt; to be made and help is welcome.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Change object after saving all inlines in Django Admin</title>
   <link href="http://igorsobreira.com/2011/02/12/change-object-after-saving-all-inlines-in-django-admin.html"/>
   <updated>2011-02-12T00:00:00-10:00</updated>
   <id>http://igorsobreira.com/2011/02/12/change-object-after-saving-all-inlines-in-django-admin</id>
   <content type="html">&lt;blockquote&gt;&lt;p&gt;&lt;strong&gt;UPDATE Aug, 2011&lt;/strong&gt;: &lt;a href=&quot;https://code.djangoproject.com/ticket/16115&quot;&gt;This patch&lt;/a&gt; added a new hook to &lt;code&gt;ModelAdmin&lt;/code&gt; called &lt;code&gt;save_related()&lt;/code&gt;. You don't need the &lt;em&gt;hack&lt;/em&gt; described bellow anymore :).&lt;/p&gt;&lt;/blockquote&gt;

&lt;hr /&gt;

&lt;p&gt;Admin is an awesome Django builtin app to create nice CRUDs for your models, and offers a lot of customizations hooks. You can personalize the templates, perform custom filters, modify newly created objects and if that's not enough, you can always create your own view to do something it doesn't by default.&lt;/p&gt;

&lt;p&gt;The &lt;a href=&quot;http://docs.djangoproject.com/en/dev/ref/contrib/admin/&quot;&gt;admin docs are great&lt;/a&gt;, I'm not going to explain how it works. The intention here is to show a way to modify an object, after it's saved, and other objects related to it using &lt;a href=&quot;http://docs.djangoproject.com/en/dev/ref/contrib/admin/#inlinemodeladmin-objects&quot;&gt;inlines&lt;/a&gt; are saved too.&lt;/p&gt;

&lt;p&gt;Once you've configured your admin interface with inlines, you end up with something similar to:&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;python&quot;&gt;&lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;django.contrib&lt;/span&gt; &lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;admin&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;fooapp.models&lt;/span&gt; &lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Foo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Related&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;RelatedInline&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;admin&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;TabularInline&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;model&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Related&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;FooAdmin&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;admin&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ModelAdmin&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;inlines&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;RelatedInline&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;admin&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;site&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;register&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Foo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;FooAdmin&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;this mean whens you're adding a &lt;code&gt;Foo&lt;/code&gt;, since &lt;code&gt;Related&lt;/code&gt; has a foreign key to it, django will display a few forms to add &lt;code&gt;Related&lt;/code&gt;s in the same page.&lt;/p&gt;

&lt;p&gt;Imagine you need to do something with the new &lt;code&gt;foo&lt;/code&gt; instance that needs to now how many &lt;code&gt;related&lt;/code&gt; objects it has. &lt;a href=&quot;http://docs.djangoproject.com/en/dev/ref/contrib/admin/#modeladmin-methods&quot;&gt;Admin already has methods you can override&lt;/a&gt; to do something after &lt;code&gt;Foo&lt;/code&gt; is saved, like &lt;code&gt;ModelAdmin.save_model()&lt;/code&gt;. See how it works:&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;python&quot;&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;FooAdmin&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;admin&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ModelAdmin&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;inlines&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;RelatedInline&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;save_model&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;request&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;obj&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;form&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;change&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;obj&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;save&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
        &lt;span class=&quot;c&quot;&gt;# do something with obj.related_set.all()&lt;/span&gt;
        &lt;span class=&quot;c&quot;&gt;# OPS! it&amp;#39;s empty!&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;admin&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;site&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;register&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Foo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;FooAdmin&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;the problem here is that &lt;code&gt;save_model()&lt;/code&gt; is called &lt;strong&gt;before&lt;/strong&gt; the inlines are saved.&lt;/p&gt;

&lt;p&gt;Let's find out how it works. Open django source code, specifically in &lt;a href=&quot;http://code.djangoproject.com/browser/django/trunk/django/contrib/admin/options.py&quot;&gt;django.contrib.admin.options.py&lt;/a&gt; go to &lt;code&gt;add_view()&lt;/code&gt;, it's the view called when you are creating an object. As you can see, when the request method is &quot;POST&quot; it goes through all validation, for the main form and all related formsets (your inlines). And if all of then are valid it calls &lt;code&gt;save_model()&lt;/code&gt;, then &lt;code&gt;save_formset()&lt;/code&gt; for each formset. The interesting piece is shown below:&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;python&quot;&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;ModelAdmin&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;BaseModelAdmin&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;

    &lt;span class=&quot;c&quot;&gt;# ...&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;add_view&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;request&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;form_url&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;#39;&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;extra_context&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;None&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
        
        &lt;span class=&quot;c&quot;&gt;# ... all validation here ...&lt;/span&gt;
        
        &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;all_valid&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;formsets&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;and&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;form_validated&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
            &lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;save_model&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;request&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;new_object&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;form&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;change&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;False&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;form&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;save_m2m&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;formset&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;formsets&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
                &lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;save_formset&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;request&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;form&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;formset&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;change&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;False&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

            &lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;log_addition&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;request&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;new_object&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;response_add&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;request&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;new_object&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;Notice here that the last method it calls is &lt;code&gt;response_add()&lt;/code&gt;, and it passes the created object, that's all we need! If you see the &lt;code&gt;change_view()&lt;/code&gt; method (witch it the view called when you're editing an object) it calls a similar method: &lt;code&gt;response_change()&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Now we can solve our problem doing something like this:&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;python&quot;&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;FooAdmin&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;admin&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ModelAdmin&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;inlines&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;RelatedInline&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;response_add&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;request&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;new_object&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;obj&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;after_saving_model_and_related_inlines&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;new_object&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;super&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;FooAdmin&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;response_add&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;request&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;obj&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;response_change&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;request&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;obj&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;obj&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;after_saving_model_and_related_inlines&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;obj&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;super&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;FooAdmin&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;response_change&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;request&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;obj&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;after_saving_model_and_related_inlines&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;obj&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;print&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;obj&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;related_set&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;all&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
        &lt;span class=&quot;c&quot;&gt;# now we have what we need here... :)&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;obj&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;There are two things to keep in mind when using these methods:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;They are not documented. So probably it's not part of the API admin expects you to override. Thankfully django publishes excellent release notes including backwards incompatible changes. And I hope you have good test coverage to know if it will break when you update django :)&lt;/li&gt;
&lt;li&gt;Their intention is to handle the response of the view, as it docstring says: &quot;Determines the HttpResponse for the add_view stage&quot;. So if you do something there not related to it, it works, wont make much sense if you look at the overall architecture.&lt;/li&gt;
&lt;/ul&gt;


&lt;p&gt;Maybe django will add a more specific hook to solve this issue later, but I hope it helps you for now.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Adding methods dynamically in Python</title>
   <link href="http://igorsobreira.com/2011/02/06/adding-methods-dynamically-in-python.html"/>
   <updated>2011-02-06T00:00:00-10:00</updated>
   <id>http://igorsobreira.com/2011/02/06/adding-methods-dynamically-in-python</id>
   <content type="html">&lt;p&gt;Given the dynamic nature of Python you can do many things in runtime, like add methods dynamically to an object or class. This is particularly useful when writing unit tests.&lt;/p&gt;

&lt;p&gt;Here is the simplest way, adding a method to and object:&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;python&quot;&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Person&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;object&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;pass&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;play&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;():&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;print&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;quot;i&amp;#39;m playing!&amp;quot;&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;p&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Person&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;p&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;play&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;play&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;p&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;play&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;note that &lt;code&gt;play&lt;/code&gt; is just a function, it doesn't receive self. There is no way to &lt;code&gt;p&lt;/code&gt; knows that it's a method. If you need &lt;code&gt;self&lt;/code&gt;, you must create a method and then bind to the object:&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;python&quot;&gt;&lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;types&lt;/span&gt; &lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;MethodType&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Person&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;object&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;__init__&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
        &lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;name&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;name&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;play&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;print&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;%s&lt;/span&gt;&lt;span class=&quot;s&quot;&gt; is playing!&amp;quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;%&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;name&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;p&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Person&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;igor&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;p&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;play&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;MethodType&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;play&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;p&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;p&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;play&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;In these examples, only the &lt;code&gt;p&lt;/code&gt; instance will have &lt;code&gt;play&lt;/code&gt; method, other instances of &lt;code&gt;Person&lt;/code&gt; won't. To accomplish this we need to add the method to the class:&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;python&quot;&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Person&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;object&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;__init__&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
        &lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;name&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;name&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;play&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;print&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;%s&lt;/span&gt;&lt;span class=&quot;s&quot;&gt; is playing!&amp;quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;%&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;name&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;Person&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;play&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;play&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;p1&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Person&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;igor&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;p1&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;play&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;p2&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Person&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;joh&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;p2&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;play&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;note that we don't need to create a method with &lt;code&gt;types.MethodType&lt;/code&gt; here, because all functions in the body of a class will become methods and receive &lt;code&gt;self&lt;/code&gt;, unless you explicit say it's a &lt;code&gt;classmethod&lt;/code&gt; or &lt;code&gt;staticmethod&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;Adding methods to builtin types&lt;/h2&gt;

&lt;p&gt;Python doesn't allow to add methods to built-in types, actually to any type defined in C. The unique way around this is to subclass the type, here is an example:&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;python&quot;&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;UpperList&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;list&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;pass&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;to_upper&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;index&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;item&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;enumerate&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
        &lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;index&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;item&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;upper&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;UpperList&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;to_upper&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;to_upper&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;l&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;UpperList&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;([&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;#39;i&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;#39;g&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;#39;o&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;#39;r&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;l&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;to_upper&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;print&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;l&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;&lt;a href=&quot;http://codeblog.dhananjaynene.com/2010/01/dynamically-adding-methods-with-metaprogramming-ruby-and-python/&quot;&gt;Here is a nice comparison on dynamically adding methods in Python and Ruby.&lt;/a&gt;&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Mocks, Stubs, Fakes and Spies</title>
   <link href="http://igorsobreira.com/2010/12/15/mocks-stubs-fakes-spies.html"/>
   <updated>2010-12-15T00:00:00-10:00</updated>
   <id>http://igorsobreira.com/2010/12/15/mocks-stubs-fakes-spies</id>
   <content type="html">&lt;p&gt;Reading the &lt;a href=&quot;http://continuousdelivery.com/&quot;&gt;Continous Delivery&lt;/a&gt; book I found a good definition of mocks, fakes, stubs and spies:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&quot;Fake objects actually have working implementations, but usually take some shortcut which makes them not suitable for production. A good example of this is the in-memory database.&lt;/li&gt;
&lt;li&gt;Stubs provide canned answers to calls made during the test, usually not responding at all to anything outside what’s programmed in for the test.&lt;/li&gt;
&lt;li&gt;Spies are stubs that also record some information based on how they were called. One form of this might be an email service that records how many messages it was sent.&lt;/li&gt;
&lt;li&gt;Mocks are pre-programmed with expectations which form a specification of the calls they are expected to receive. They can throw an exception if they receive a call they don’t expect and are checked during verification to ensure they got all the calls they were expecting.&quot;&lt;/li&gt;
&lt;/ul&gt;


&lt;p&gt;This terminology was taken from &lt;a href=&quot;http://www.amazon.com/xUnit-Test-Patterns-Refactoring-Code/dp/0131495054&quot;&gt;xUnit Test Patterns&lt;/a&gt; book.&lt;/p&gt;

&lt;p&gt;I've already seen cases where people write lot's of unit tests, abusing from mock objects, but without good integration and acceptance tests you can't really guarantee that each scenario is really working as expected.&lt;/p&gt;

&lt;blockquote&gt;&lt;p&gt;&quot;It’s very easy to misuse mocks to write tests that are both pointless and fragile, using them simply to assert the specific details of the workings of some code, rather than an assertion of interactions with collaborators.&quot;&lt;/p&gt;&lt;/blockquote&gt;

&lt;p&gt;A couple links if you want to read more about it:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;http://www.jmock.org/oopsla2004.pdf&quot;&gt;Mock Roles, Not Object&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://martinfowler.com/articles/mocksArentStubs.html&quot;&gt;Mocks Aren't Stubs&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</content>
 </entry>
 
 <entry>
   <title>Extending the User model in Django</title>
   <link href="http://igorsobreira.com/2010/12/11/extending-user-model-in-django.html"/>
   <updated>2010-12-11T00:00:00-10:00</updated>
   <id>http://igorsobreira.com/2010/12/11/extending-user-model-in-django</id>
   <content type="html">&lt;p&gt;Django brings a built-in &lt;a href=&quot;http://docs.djangoproject.com/en/1.2/topics/auth/&quot;&gt;user authentication system&lt;/a&gt;, it includes an &lt;a href=&quot;http://docs.djangoproject.com/en/1.2/topics/auth/#users&quot;&gt;User model&lt;/a&gt; which has the most common attributes. But in most applications you may need to store additional attributes to users. Django &lt;a href=&quot;http://docs.djangoproject.com/en/1.2/topics/auth/#storing-additional-information-about-users&quot;&gt;has a way to do this&lt;/a&gt; too.&lt;/p&gt;

&lt;h2&gt;Extending using foreign key&lt;/h2&gt;

&lt;p&gt;Basically you create your &lt;code&gt;UserProfile&lt;/code&gt; model with a &lt;code&gt;OneToOneField&lt;/code&gt; to &lt;code&gt;User&lt;/code&gt;:&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;python&quot;&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;UserProfile&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;models&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Model&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;user&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;models&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;OneToOneField&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;#39;auth.User&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;bio&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;models&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;TextField&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
    &lt;span class=&quot;c&quot;&gt;# ...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;and define in on settings.py&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;python&quot;&gt;&lt;span class=&quot;n&quot;&gt;AUTH_PROFILE_MODULE&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;#39;accounts.UserProfile&amp;#39;&lt;/span&gt;     &lt;span class=&quot;c&quot;&gt;# app name (dot) model name&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;From now on your &lt;code&gt;User&lt;/code&gt; objects will have a &lt;code&gt;get_profile()&lt;/code&gt; method.&lt;/p&gt;

&lt;p&gt;I personally can't see a reason to use this setting (and I hate &quot;getters&quot; methods), you just need to do this:&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;python&quot;&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;UserProfile&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;models&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Model&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;user&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;models&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;OneToOneField&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;#39;auth.User&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;related_name&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;#39;profile&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;bio&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;models&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;TextField&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
    &lt;span class=&quot;c&quot;&gt;# ...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;See the &lt;code&gt;related_name='profile'&lt;/code&gt; parameter, now you don't need the &lt;code&gt;get_profile()&lt;/code&gt; method anymore, just use &lt;code&gt;user_instance.profile&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;But there is a small problem here, if the user instance don't have a profile related to it you will receive an &lt;code&gt;ObjectDoesNotExist&lt;/code&gt; exception. This happens with &lt;code&gt;get_profile()&lt;/code&gt; too. And it's not good to handle the exception every time you access the profile. The simplest way to solve this is connect to &lt;a href=&quot;http://docs.djangoproject.com/en/1.2/ref/signals/#django.db.models.signals.post_save&quot;&gt;&lt;code&gt;django.db.models.signals.post_save&lt;/code&gt;&lt;/a&gt; on the &lt;code&gt;User&lt;/code&gt; model and create your &lt;code&gt;UserProfile&lt;/code&gt; instance related to it&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;python&quot;&gt;&lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;django.db.models&lt;/span&gt; &lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;signals&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;accounts.models&lt;/span&gt; &lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;UserProfile&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;create_user_profile&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;sender&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;instance&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;created&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;**&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;kwargs&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;created&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;UserProfile&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;objects&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;create&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;user&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;instance&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;signals&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;post_save&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;connect&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;create_user_profile&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;sender&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;User&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;h2&gt;Why subclassing User is a bad idea&lt;/h2&gt;

&lt;p&gt;There are a few reasons I prefer to create user profiles as another model instead of just subclassing the default User. If you think for a while, an user has a lot to do in your site, and there are at a few default steps:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;first she needs to register, confirm by email, and so on&lt;/li&gt;
&lt;li&gt;login and logout, change and reset password&lt;/li&gt;
&lt;li&gt;admins may need to manage groups and permissions, to restrict user actions, offer features to specific groups&lt;/li&gt;
&lt;li&gt;manage profile, with personal information&lt;/li&gt;
&lt;/ul&gt;


&lt;p&gt;Django doesn't handle the first topic, there is a &lt;a href=&quot;http://djangopackages.com/packages/p/django-registration/&quot;&gt;great app to handle registration&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The second and third topics can be done with &lt;code&gt;django.contrib.auth&lt;/code&gt; app, this is exactly it's purpose.&lt;/p&gt;

&lt;p&gt;And then you have the forth topic, which is profiles. As you can see, it can be done as a separate app. A user &lt;em&gt;has&lt;/em&gt; a profile. So makes sense to have a &lt;code&gt;profile&lt;/code&gt; attribute in the User object.&lt;/p&gt;

&lt;p&gt;If you split features in apps like this it's easier to reuse too, that's the idea of django apps after all! The &lt;a href=&quot;http://djangopackages.com/packages/p/django-registration/&quot;&gt;django-registration&lt;/a&gt; is an example. And as you can imagine, there &lt;a href=&quot;http://djangopackages.com/grids/g/profiles/&quot;&gt;are apps to manage profiles&lt;/a&gt; too.&lt;/p&gt;

&lt;h2&gt;Editing User profile in admin&lt;/h2&gt;

&lt;p&gt;If you're using admin you may want to edit the UserProfile fields in the same page as the User fields, and it's possible using &lt;a href=&quot;http://docs.djangoproject.com/en/1.2/ref/contrib/admin/#inlinemodeladmin-objects&quot;&gt;admin inlines&lt;/a&gt;. Here is how you admin configuration will look like:&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;python&quot;&gt;&lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;django.contrib&lt;/span&gt; &lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;admin&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;django.contrib.auth.admin&lt;/span&gt; &lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;UserAdmin&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;DjangoUserAdmin&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;django.contrib.auth.models&lt;/span&gt; &lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;User&lt;/span&gt;

&lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;accounts.models&lt;/span&gt; &lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;UserProfile&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;UserProfileInline&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;admin&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;TabularInline&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;model&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;UserProfile&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;UserAdmin&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;DjangoUserAdmin&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;inlines&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;UserProfileInline&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,)&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;admin&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;site&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;unregister&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;User&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;admin&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;site&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;register&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;User&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;UserAdmin&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;h2&gt;Conclusion&lt;/h2&gt;

&lt;p&gt;As you can see, it quite easy to manage user profiles in django. Although there is a way to hook you profile model in settings.py, you can do it with a simple foreign key. And as usual, there are a few reusable apps around to handle the generic stuff.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Slides - Desenvolvimento web com Python e Django</title>
   <link href="http://igorsobreira.com/2010/11/08/slides-desenvolvimento-web-com-python-e-django.html"/>
   <updated>2010-11-08T00:00:00-10:00</updated>
   <id>http://igorsobreira.com/2010/11/08/slides-desenvolvimento-web-com-python-e-django</id>
   <content type="html">&lt;p&gt;Segue os slides da minha palestra &lt;strong&gt;Desenvolvimento web com Python e Django&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Apresentei essa palestra no &lt;a href=&quot;http://lti.cesed.br/apps/jatic/&quot;&gt;Jatic&lt;/a&gt;, na faculdade Facisa em Campina Grande, PB. E também no &lt;a href=&quot;http://www.univem.edu.br/gwsites/default.asp?site=citos&quot;&gt;CITOS&lt;/a&gt;, na faculdade Univem, em Marília, SP.&lt;/p&gt;

&lt;p&gt;A maior parte da apresentação fala sobre Django, mas também mostra como funciona o WSGI, as maneiras mais comuns de fazer deployment de aplicações em python hoje em dia, configuração de ambiente usando virtualenv, testes...&lt;/p&gt;

&lt;div style=&quot;width:425px&quot; id=&quot;__ss_5708711&quot;&gt;&lt;strong style=&quot;display:block;margin:12px 0 4px&quot;&gt;&lt;a href=&quot;http://www.slideshare.net/igorsobreira/desenvolvimento-web-com-python-e-django&quot; title=&quot;Desenvolvimento web com python e django&quot;&gt;Desenvolvimento web com python e django&lt;/a&gt;&lt;/strong&gt;&lt;object id=&quot;__sse5708711&quot; width=&quot;425&quot; height=&quot;355&quot;&gt;&lt;param name=&quot;movie&quot; value=&quot;http://static.slidesharecdn.com/swf/ssplayer2.swf?doc=desenvolvimentowebcompythonedjango-101108180250-phpapp01&amp;stripped_title=desenvolvimento-web-com-python-e-django&amp;userName=igorsobreira&quot; /&gt;&lt;param name=&quot;allowFullScreen&quot; value=&quot;true&quot;/&gt;&lt;param name=&quot;allowScriptAccess&quot; value=&quot;always&quot;/&gt;&lt;embed name=&quot;__sse5708711&quot; src=&quot;http://static.slidesharecdn.com/swf/ssplayer2.swf?doc=desenvolvimentowebcompythonedjango-101108180250-phpapp01&amp;stripped_title=desenvolvimento-web-com-python-e-django&amp;userName=igorsobreira&quot; type=&quot;application/x-shockwave-flash&quot; allowscriptaccess=&quot;always&quot; allowfullscreen=&quot;true&quot; width=&quot;425&quot; height=&quot;355&quot;&gt;&lt;/embed&gt;&lt;/object&gt;&lt;div style=&quot;padding:5px 0 12px&quot;&gt;

Veja outras aprensentações minhas no &lt;a href=&quot;http://www.slideshare.net/igorsobreira&quot;&gt;Slideshare&lt;/a&gt;.&lt;/div&gt;&lt;/div&gt;

</content>
 </entry>
 
 <entry>
   <title>Campos numéricos localizados no Django</title>
   <link href="http://igorsobreira.com/2010/09/25/campos-numericos-localizados-no-django.html"/>
   <updated>2010-09-25T00:00:00-10:00</updated>
   <id>http://igorsobreira.com/2010/09/25/campos-numericos-localizados-no-django</id>
   <content type="html">&lt;p&gt;A criação de campos numéricos ficou muito &lt;a href=&quot;http://docs.djangoproject.com/en/1.2/topics/i18n/localization/#format-localization&quot;&gt;mais fácil no Django na versão 1.2&lt;/a&gt;. Imagine o seguinte model:&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;python&quot;&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Debito&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;models&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Model&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;descricao&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;models&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;CharField&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;max_length&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;256&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;valor&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;models&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;DecimalField&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;max_digits&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;decimal_places&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    
    &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;unicode&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;descricao&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;E seu registro no admin&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;python&quot;&gt;&lt;span class=&quot;n&quot;&gt;admin&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;site&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;register&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Debito&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;Ao tentar cadastrar um valor numérico, por exemplo: 1.450,60, receberíamos um erro já que esse formato não era entendido como numérico. Agora, basta informar que esse campo precisa ser localizado. Como isso é feito no formulário, e não no model, vamos sobrescrever o formulário padrão do admin&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;python&quot;&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;DebitoForm&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;forms&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ModelForm&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;valor&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;forms&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;DecimalField&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;max_digits&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;decimal_places&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;localize&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;True&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Meta&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;model&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Debito&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;DebitoAdmin&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;admin&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ModelAdmin&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;form&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;DebitoForm&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;admin&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;site&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;register&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Debito&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;DebitoAdmin&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;Note o parâmetro &lt;code&gt;localize&lt;/code&gt; no campo &lt;code&gt;DecimalField&lt;/code&gt; do formulário.&lt;/p&gt;

&lt;p&gt;Estamos quase lá, só precisamos nos certificar de que as seguintes configurações estão no settings.py&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;python&quot;&gt;&lt;span class=&quot;n&quot;&gt;USE_L10N&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;True&lt;/span&gt;         &lt;span class=&quot;c&quot;&gt;# essa é padrão&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;USE_THOUSAND_SEPARATOR&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;True&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;Mas ainda tem um detalhe, se você tentar acessar &lt;code&gt;debito.valor&lt;/code&gt; vai receber uma instância da classe &lt;code&gt;decimal.Decimal&lt;/code&gt; do python, e ainda terá que formatar manualmente. Felizmente o django já possui uma função pra fazer isso. Para facilitar, você pode adicionar um método no seu model:&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;python&quot;&gt;&lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;django.utils.formats&lt;/span&gt; &lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;number_format&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Debito&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;models&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Model&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;descricao&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;models&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;CharField&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;max_length&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;256&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;valor&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;models&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;DecimalField&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;max_digits&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;decimal_places&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;__unicode__&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;descricao&lt;/span&gt;

    &lt;span class=&quot;nd&quot;&gt;@property&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;valor_formatado&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;u&amp;quot;R$ &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;%s&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;%&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;number_format&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;valor&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; 
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;Agora sim, basta acessar &lt;code&gt;debito.valor_formatado&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Confira &lt;a href=&quot;http://docs.djangoproject.com/en/1.2/topics/i18n/localization/#format-localization&quot;&gt;a documentação para mais detalhes&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Até a próxima!&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Difference between _, __ and __xx__ in Python</title>
   <link href="http://igorsobreira.com/2010/09/16/difference-between-one-underline-and-two-underlines-in-python.html"/>
   <updated>2010-09-16T00:00:00-10:00</updated>
   <id>http://igorsobreira.com/2010/09/16/difference-between-one-underline-and-two-underlines-in-python</id>
   <content type="html">&lt;p&gt;When learning Python many people don't really understand why so much underlines in the beginning of the methods, sometimes even in the end like &lt;code&gt;__this__&lt;/code&gt;! I've already had to explain it so many times, it's time to document it.&lt;/p&gt;

&lt;h2&gt;One underline in the beginning&lt;/h2&gt;

&lt;p&gt;Python doesn't have real private methods, so one underline in the beginning of a method or attribute means you shouldn't access this method, because it's not part of the API. It's very common when using properties:&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;python&quot;&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;BaseForm&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;StrAndUnicode&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;...&lt;/span&gt;
    
    &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;_get_errors&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
        &lt;span class=&quot;s&quot;&gt;&amp;quot;Returns an ErrorDict for the data provided for the form&amp;quot;&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;_errors&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;is&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;None&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
            &lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;full_clean&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;_errors&lt;/span&gt;
    
    &lt;span class=&quot;n&quot;&gt;errors&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;property&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;_get_errors&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;This snippet was taken from django source code (django/forms/forms.py). This means &lt;code&gt;errors&lt;/code&gt; is a property, and it's part of the API, but the method this property calls, &lt;code&gt;_get_errors&lt;/code&gt;, is &quot;private&quot;, so you shouldn't access it.&lt;/p&gt;

&lt;h2&gt;Two underlines in the beginning&lt;/h2&gt;

&lt;p&gt;This one causes a lot of confusion. It should &lt;strong&gt;not&lt;/strong&gt; be used to mark a method as private, the goal here is to avoid your method to be overridden by a subclass. Let's see an example:&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;python&quot;&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;object&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;__method&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;print&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;quot;I&amp;#39;m a method in A&amp;quot;&lt;/span&gt;
    
    &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;method&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
        &lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;__method&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
     
&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;method&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;The output here is&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;$ python example.py 
I'm a method in A
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Fine, as we expected. Now let's subclass &lt;code&gt;A&lt;/code&gt; and customize &lt;code&gt;__method&lt;/code&gt;&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;python&quot;&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;B&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;__method&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;print&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;quot;I&amp;#39;m a method in B&amp;quot;&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;b&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;B&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;method&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;and now the output is...&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;$ python example.py
I'm a method in A
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;as you can see, &lt;code&gt;A.method()&lt;/code&gt; didn't call &lt;code&gt;B.__method()&lt;/code&gt; as we could expect. Actually this is the correct behavior for &lt;code&gt;__&lt;/code&gt;. So when you create a method starting with &lt;code&gt;__&lt;/code&gt; you're saying that you don't want anybody to override it, it will be accessible just from inside the own class.&lt;/p&gt;

&lt;p&gt;How python does it? Simple, it just renames the method. Take a look:&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;python&quot;&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;_A__method&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;  &lt;span class=&quot;c&quot;&gt;# never use this!! please!&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;pre&gt;&lt;code&gt;$ python example.py
I'm a method in A
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;If you try to access &lt;code&gt;a.__method()&lt;/code&gt; it won't work either, as I said, &lt;code&gt;__method&lt;/code&gt; is just accessible inside the class itself.&lt;/p&gt;

&lt;h2&gt;Two underlines in the beginning and in the end&lt;/h2&gt;

&lt;p&gt;When you see a method like &lt;code&gt;__this__&lt;/code&gt;, the rule is simple: don't call it. Why? Because it means it's a method python calls, not you. Take a look:&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;pycon&quot;&gt;&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;name&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;quot;igor&amp;quot;&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;__len__&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;4&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;len&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;4&lt;/span&gt;

&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;number&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;10&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;number&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;__add__&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;20&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;30&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;number&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;20&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;30&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;There is always an operator or native function that calls these &lt;em&gt;magic methods&lt;/em&gt;. The idea here is to give you the ability to override operators in your own classes. Sometimes it's just a hook python calls in specific situations. &lt;code&gt;__init__()&lt;/code&gt;, for example, is called when the object is created so you can initialize it. &lt;code&gt;__new__()&lt;/code&gt; is called to build the instance, and so on...&lt;/p&gt;

&lt;p&gt;Here's an example:&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;python&quot;&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;CrazyNumber&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;object&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
    
    &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;__init__&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;n&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
        &lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;n&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;n&lt;/span&gt;
    
    &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;__add__&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;other&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;n&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;other&lt;/span&gt;
    
    &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;__sub__&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;other&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;n&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;other&lt;/span&gt;
    
    &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;__str__&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;str&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;n&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;


&lt;span class=&quot;n&quot;&gt;num&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;CrazyNumber&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;print&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;num&lt;/span&gt;           &lt;span class=&quot;c&quot;&gt;# 10&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;print&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;num&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;       &lt;span class=&quot;c&quot;&gt;# 5&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;print&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;num&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;20&lt;/span&gt;      &lt;span class=&quot;c&quot;&gt;# 30&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;Another example:&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;python&quot;&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Room&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;object&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;__init__&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
        &lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;people&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[]&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;add&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;person&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
        &lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;people&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;append&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;person&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;__len__&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;len&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;people&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;room&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Room&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;room&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;add&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;Igor&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;print&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;len&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;room&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;     &lt;span class=&quot;c&quot;&gt;# 1&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;The &lt;a href=&quot;http://docs.python.org/reference/datamodel.html#special-method-names&quot;&gt;documentation&lt;/a&gt; covers all these special methods.&lt;/p&gt;

&lt;h2&gt;Conclusion&lt;/h2&gt;

&lt;p&gt;Use &lt;code&gt;_one_underline&lt;/code&gt; to mark you methods as not part of the API. Use &lt;code&gt;__two_underlines__&lt;/code&gt; when you're creating objects to look like native python objects or you wan't to customize behavior in specific situations. And don't use &lt;code&gt;__just_to_underlines&lt;/code&gt;, unless you really know what you're doing!&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Customize settings.py locally in Django</title>
   <link href="http://igorsobreira.com/2010/09/12/customize-settingspy-locally-in-django.html"/>
   <updated>2010-09-12T00:00:00-10:00</updated>
   <id>http://igorsobreira.com/2010/09/12/customize-settingspy-locally-in-django</id>
   <content type="html">&lt;p&gt;The django configuration file is pure python code, this gives us a lot of flexibility to setup settings when the application starts. Actually you could even modify settings in runtime, but promise me you won't do this, ever!&lt;/p&gt;

&lt;p&gt;Imagine you have an open-source django project, you have your code in github or something like that, but you probably don't want to publish your DATABASES configuration. Or maybe you can add all your server configuration under version control, it's private, great, but your local configuration is probably different too, you will need to set DEBUG = True at least.&lt;/p&gt;

&lt;p&gt;There are a few ways to extend the settings.py file...&lt;/p&gt;

&lt;h2&gt;Use the --settings option&lt;/h2&gt;

&lt;p&gt;The manage.py command has a &lt;code&gt;--settings&lt;/code&gt; option that you can use to specify a different settings file, so you could have a local_settings.py file similar to:&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;python&quot;&gt;&lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;settings&lt;/span&gt; &lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; 

&lt;span class=&quot;n&quot;&gt;DEBUG&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;True&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;DATABASES&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;&amp;#39;default&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;s&quot;&gt;&amp;#39;ENGINE&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;#39;django.db.backends.sqlite3&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;s&quot;&gt;&amp;#39;NAME&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;#39;db.sqlite&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;s&quot;&gt;&amp;#39;USER&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;#39;&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;s&quot;&gt;&amp;#39;PASSWORD&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;#39;&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;s&quot;&gt;&amp;#39;HOST&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;#39;&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;s&quot;&gt;&amp;#39;PORT&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;#39;&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;And locally you use:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;$ python manage.py runserver --settings=local_settings
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This is the simplest way to extend the settings.py file and is probably enough for most situations, but let's take a look in other options.&lt;/p&gt;

&lt;h2&gt;Importing from settings.py&lt;/h2&gt;

&lt;p&gt;This method is the opposite from above. In the end of your settings.py you add:&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;python&quot;&gt;&lt;span class=&quot;k&quot;&gt;try&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;local_settings&lt;/span&gt; &lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; 
&lt;span class=&quot;n&quot;&gt;expect&lt;/span&gt; &lt;span class=&quot;ne&quot;&gt;ImportError&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;pass&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;Now you local_settings.py file won't need to import anything from settings.py, just set your configuration variables. And you don't need to pass &lt;code&gt;--settings&lt;/code&gt; anymore.&lt;/p&gt;

&lt;h2&gt;Adding code dynamically to settings.py&lt;/h2&gt;

&lt;p&gt;This is similar to the method above but gives you more flexibility. Imagine you need a local_settings.py file similiar to this:&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;python&quot;&gt;&lt;span class=&quot;n&quot;&gt;DEBUG&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;True&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;INTERNAL_IPS&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;#39;127.0.0.1&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;MIDDLWARE_CLASSES&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;MIDDLWARE_CLASSES&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;#39;debug_toolbar.middleware.DebugToolbarMiddleware&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;INSTALLED_APPS&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;INSTALLED_APPS&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;#39;debug_toolbar&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;How could you use &lt;code&gt;MIDDLWARE_CLASSES&lt;/code&gt; or &lt;code&gt;INSTALLED_APPS&lt;/code&gt; from settings.py if you didn't import those? Here is the answer:&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;python&quot;&gt;&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;os&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;PROJECT_ROOT&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;os&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;path&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;dirname&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;file&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;try&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;nb&quot;&gt;execfile&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;os&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;path&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;join&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;PROJECT_ROOT&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;#39;local_settings.py&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;globals&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(),&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;locals&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;())&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;except&lt;/span&gt; &lt;span class=&quot;ne&quot;&gt;IOError&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;pass&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;The trick here is the &lt;a href=&quot;http://docs.python.org/library/functions.html#execfile&quot;&gt;execfile&lt;/a&gt; function, it reads the content of the file and &lt;em&gt;appends&lt;/em&gt; it to the file you calling from. In the end, it's like the contents of you local_settings.py file are inside settings.py.&lt;/p&gt;

&lt;h2&gt;Host specific settings&lt;/h2&gt;

&lt;p&gt;Now you already have a way to customize your settings locally, just create a local_settings.py file, don't add it under version control, and add one of these code snippets in the end of your settings.py.&lt;/p&gt;

&lt;p&gt;But what if you need specific settings per host? You have this project that runs on multiple servers, and you want specific settings for each one. You could create a settings_&lt;SERVER_HOSTNAME&gt;.py file, and import dynamically:&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;python&quot;&gt;&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;socket&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;os&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;PROJECT_ROOT&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;os&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;path&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;dirname&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;file&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;settings&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;#39;settings_&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;%s&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;.py&amp;#39;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;%&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;socket&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;gethostname&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;try&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;nb&quot;&gt;execfile&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;os&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;path&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;join&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;PROJECT_ROOT&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;settings&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;globals&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(),&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;locals&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;())&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;except&lt;/span&gt; &lt;span class=&quot;ne&quot;&gt;IOError&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;pass&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;To view your hostname just execute:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;$ hostname
globo-mac
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;so, in my case I have a file called settings_globo-mac.py&lt;/p&gt;

&lt;h2&gt;Conclusion&lt;/h2&gt;

&lt;p&gt;That's it! How I said in the beginning, settings.py is just python, this gives us a lot of power to customize our settings dynamically. If you have another idea let us know.&lt;/p&gt;

&lt;p&gt;See you!&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Replacing render_to_response with direct_to_template in Django</title>
   <link href="http://igorsobreira.com/2010/09/11/replacing-render_do_response-with-direct_to_template-in-django.html"/>
   <updated>2010-09-11T00:00:00-10:00</updated>
   <id>http://igorsobreira.com/2010/09/11/replacing-render_do_response-with-direct_to_template-in-django</id>
   <content type="html">&lt;blockquote&gt;&lt;p&gt;&lt;strong&gt;Update&lt;/strong&gt;: September 3, 2012&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://docs.djangoproject.com/en/1.4/topics/http/shortcuts/#render&quot;&gt;A &lt;code&gt;render()&lt;/code&gt;&lt;/a&gt; &lt;a href=&quot;https://docs.djangoproject.com/en/1.4/releases/1.3/#everything-else&quot;&gt;was introduced on Django 1.3&lt;/a&gt; to use &lt;code&gt;RequestContext&lt;/code&gt; by default&lt;/p&gt;&lt;/blockquote&gt;

&lt;p&gt;You certainly have already used &lt;code&gt;render_to_response&lt;/code&gt; to render your templates, it's a very convenient shortcut:&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;python&quot;&gt;&lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;django.shortcuts&lt;/span&gt; &lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;render_to_response&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;myview&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;request&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;...&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;render_to_response&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;#39;template.html&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;#39;foo&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;#39;one&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;#39;two&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;At least until you need to use &lt;a href=&quot;http://docs.djangoproject.com/en/1.2/ref/templates/api/#subclassing-context-requestcontext&quot;&gt;context processors&lt;/a&gt;, then you start writing code like this&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;python&quot;&gt;&lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;django.shortcuts&lt;/span&gt; &lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;render_to_response&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;django.template&lt;/span&gt; &lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;RequestContext&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;myview&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;request&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;...&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;render_to_response&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;#39;template.html&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; 
            &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;#39;foo&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;#39;one&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;#39;two&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]},&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;context_instance&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;RequestContext&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;request&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;this &lt;code&gt;context_instance&lt;/code&gt; argument is the boilerplate code you will always need to make context processors work. I think it's too much typing, and I'm lazy, so I prefer to use the &lt;code&gt;direct_to_template&lt;/code&gt; generic view:&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;python&quot;&gt;&lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;django.views.generic.simple&lt;/span&gt; &lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;direct_to_template&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;myview&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;request&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;...&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;direct_to_template&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;request&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;#39;template.html&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; 
            &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;#39;foo&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;#39;one&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;#39;two&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;You don't need the &lt;code&gt;context_instance&lt;/code&gt; argument anymore, and you save one import.&lt;/p&gt;

&lt;p&gt;But! There is one &lt;em&gt;simple&lt;/em&gt; detail when passing extra context to this view, if a value in your dict is a callable, it will call and pass the result to template. It can be useful, but is something to keep in mind, if you're trying to pass a callable to template.&lt;/p&gt;

&lt;p&gt;Read the &lt;a href=&quot;http://code.djangoproject.com/browser/django/trunk/django/views/generic/simple.py&quot;&gt;source code&lt;/a&gt; to understand how it works.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Django readonly fields in Admin</title>
   <link href="http://igorsobreira.com/2010/02/20/django-readonly-fields-admin.html"/>
   <updated>2010-02-20T00:00:00-10:00</updated>
   <id>http://igorsobreira.com/2010/02/20/django-readonly-fields-admin</id>
   <content type="html">&lt;p&gt;Finally Django has implemented &lt;a href=&quot;http://docs.djangoproject.com/en/dev/ref/contrib/admin/#django.contrib.admin.ModelAdmin.readonly_fields&quot;&gt;readonly fields&lt;/a&gt; in Admin interface. It's a new feature in 1.2 which is in alpha version at this moment, but will be released soon.&lt;/p&gt;

&lt;p&gt;The feature is really simple and is &lt;a href=&quot;http://docs.djangoproject.com/en/dev/ref/contrib/admin/#django.contrib.admin.ModelAdmin.readonly_fields&quot;&gt;already documented&lt;/a&gt; so I won't explain how it works. But there is one implementation detail not documented that gives much more power to this feature. If you check the admin sources, you'll find a method called get_readonly_fields() in django/contrib/admin/options.py, by default it just returns self.readonly_fields, which is the normal usage, but since you receive the request object as a parameter you can enable or not some fields depending on the logged in user.&lt;/p&gt;

&lt;p&gt;Here is an example where a slug field can just be edited by superusers:&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;python&quot;&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;FooModelAdmin&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;admin&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ModelAdmin&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;...&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;get_readonly_fields&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;request&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;obj&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;None&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;request&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;user&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;is_superuser&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;#39;slug&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;There are &lt;a href=&quot;http://djangoadvent.com/1.2/&quot;&gt;lot's of interesting new features in Django 1.2&lt;/a&gt;, I'm looking forward for it!&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Python 3.1.1. error on startup</title>
   <link href="http://igorsobreira.com/2009/12/29/python3-error-on-startup.html"/>
   <updated>2009-12-29T00:00:00-10:00</updated>
   <id>http://igorsobreira.com/2009/12/29/python3-error-on-startup</id>
   <content type="html">&lt;p&gt;After installing &lt;a href=&quot;http://python.org/ftp/python/3.1.1/python-3.1.1.dmg&quot;&gt;Python 3.1.1 for Mac OS&lt;/a&gt; on my Leopard I got an error trying to start python3 from Terminal:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;$ python3
Fatal Python error: Py_Initialize: can't initialize sys standard streams
LookupError: unknown encoding: 
Abort trap
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;There is a &lt;a href=&quot;http://bugs.python.org/issue6393&quot;&gt;&quot;fixed&quot; issue&lt;/a&gt; in the bug tracker but the problem persists in my installation.
A quick workaround is to set LC_CTYPE properly. Check how it is now with the locale command (mine was UTF-8)&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;$ export LC_CTYPE=en_US.UTF-8
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Add this to your &lt;code&gt;~/.profile&lt;/code&gt;.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Ajax File Upload with jQuery</title>
   <link href="http://igorsobreira.com/2009/09/21/ajax-file-upload-with-jquery.html"/>
   <updated>2009-09-21T00:00:00-10:00</updated>
   <id>http://igorsobreira.com/2009/09/21/ajax-file-upload-with-jquery</id>
   <content type="html">&lt;p&gt;I've been looking for an Ajax upload plugin for jQuery yesterday. And actually I found some interesting solutions, but any of then did what I wanted.&lt;/p&gt;

&lt;p&gt;I needed a multi file upload. I had a form with many file inputs and I wanted it to just works, using Ajax. The options available that supports multi file upload (without flash), are limited to just one file input, and you can choose more that one file from it. It's nice, but not what I needed.&lt;/p&gt;

&lt;p&gt;Then I found this one: &lt;a href=&quot;http://www.phpletter.com/Our-Projects/AjaxFileUpload/&quot;&gt;Ajax File Upload&lt;/a&gt;. It only supports one file input too, but I've hacked it to support more that one, and still be able to send more data (the other fields values of my form) to the server.&lt;/p&gt;

&lt;p&gt;Internally it creates a new form, and put it inside an iframe, and so on. Well, it just works, and it was easy to modify for my needs.&lt;/p&gt;

&lt;h2&gt;Usage&lt;/h2&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;javascript&quot;&gt;&lt;span class=&quot;nx&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;ajaxFileUpload&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;({&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;url&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;/url/to/post/&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    
    &lt;span class=&quot;c1&quot;&gt;// here you pass a jQuery selector with all your file inputs.&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;// this is the main change I&amp;#39;ve made, in the original version you had to pass an&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;// ID of you file input&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;fileElements&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;input[type=file]&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt;
    
    &lt;span class=&quot;c1&quot;&gt;// also supports json, xml and script&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;dataType&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;html&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    
    &lt;span class=&quot;nx&quot;&gt;success&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;response&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; 
        &lt;span class=&quot;nx&quot;&gt;alert&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;hey, it worked&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;error&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;xhr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;status&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;error&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; 
        &lt;span class=&quot;nx&quot;&gt;alert&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;you&amp;#39;ve got a problem here&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
    
    &lt;span class=&quot;c1&quot;&gt;// here you pass an object with all extra data you want to send.&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;// it didn&amp;#39;t existed in the original version&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;extraData&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;foo&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;bar&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;h2&gt;Download&lt;/h2&gt;

&lt;p&gt;You can download it &lt;a href=&quot;http://arquivos.igorsobreira.com/javascript/ajaxfileupload.js&quot;&gt;here&lt;/a&gt;. And the original can be found &lt;a href=&quot;http://www.phpletter.com/Our-Projects/AjaxFileUpload/&quot;&gt;here&lt;/a&gt;, you will find more usage examples there too.&lt;/p&gt;

&lt;p&gt;If you're insterested, &lt;a href=&quot;http://arquivos.igorsobreira.com/javascript/ajaxfileupload.diff&quot;&gt;here&lt;/a&gt; is the diff with my changes.&lt;/p&gt;

&lt;p&gt;I hope it's useful for you too.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>1º Encontro do GrupyPB</title>
   <link href="http://igorsobreira.com/2009/08/21/1-encontro-grupypb.html"/>
   <updated>2009-08-21T00:00:00-10:00</updated>
   <id>http://igorsobreira.com/2009/08/21/1-encontro-grupypb</id>
   <content type="html">&lt;p&gt;&lt;img src=&quot;/assets/uploads/grupypb.png&quot; alt=&quot;GrupyPB&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Ontem teve o 1º Encontro do GrupyPB, o grupo de usuários Python aqui da Paraíba. O grupo foi criado a algum tempo, e tentamos organizar um encontro mais de uma vez, mas sempre tinha um impecilho, trabalho, universidade, etc. Dessa vez conseguimos!&lt;/p&gt;

&lt;p&gt;O encontro aconteceu na &lt;a href=&quot;http://fatecjp.com.br/&quot;&gt;FATEC&lt;/a&gt;, que deu todo o apoio e estrutura. Foi interessante ver que Python tá sendo realmente usado aqui na Paraíba em diversas áreas: web, mobile, desktop, e até conversando com Arduínos. Tivemos uma tarde de palestras, e no final tinhamos planejado um &lt;a href=&quot;http://codingdojo.org/&quot;&gt;Coding Dojo&lt;/a&gt;, que acabou virando mais um aulão de Python, já que muitos ainda não conheciam a linguagem. O que eu achei bem interessante, prova que nós próximos encontros e Dojos teremos mais &lt;em&gt;pythonistas&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;A primeira palestra foi minha, sobre Python na Web, a idéia era somente mostrar como Python pode ser usado na web. Falei um pouco sobre o padrão WSGI, uma visão sobre alguns frameworks e a possibilidade de montar o seu, usando módulos existentes.&lt;/p&gt;

&lt;p&gt;Depois &lt;a href=&quot;http://www.flavioribeiro.com/&quot;&gt;Flávio Ribeiro&lt;/a&gt; falou sobre Python na plataforma Symbian. As vantagens e desvantagens, e uma visão geral de como python tá sendo adotado no mundo de dispositivos móveis. E com direito a uma apresentação do &lt;a href=&quot;http://www.flavioribeiro.com/marmota&quot;&gt;marmota&lt;/a&gt;, um de seus projetos pessoais. Um carrinho equipado com um Arduíno controlado pelo celular com PyS60 tomou conta do auditório.&lt;/p&gt;

&lt;p&gt;Luiz Thiago falou sobre a filosofia que está por trás do Python. O Zen Of Python, a PEP 008, que propõe um estilo para os códigos ficarem o mais legível possível. Achei interessante mostrar ao pessoal novo como a comunidade e os &lt;em&gt;core developers&lt;/em&gt; prezam pela beleza de código e facilidade de leitura.&lt;/p&gt;

&lt;p&gt;Por fim, &lt;a href=&quot;http://www.raninho.com.br/&quot;&gt;Raniere Fernandes&lt;/a&gt;, ou Raninho, falou sobre Python e Qt, confesso que foi a mais esperada por mim, principalmente depois do lançamento do &lt;a href=&quot;http://www.pyside.org/&quot;&gt;PySide&lt;/a&gt; essa semana. Qt é realmente show! Fiquei muito interessado em aprender.&lt;/p&gt;

&lt;p&gt;As palestras estão acessíveis na página do encontro no site: &lt;a href=&quot;http://grupypb.net/meetings/1/&quot;&gt;grupypb.net&lt;/a&gt;. Ou direto no slideshare, na tag, &lt;a href=&quot;http://www.slideshare.net/tag/grupypb&quot;&gt;grupypb&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Espero que mais encontros venham periodicamente. Se você é daqui da Paraíba (ou não), entre no &lt;a href=&quot;http://groups.google.com/group/grupy-pb&quot;&gt;grupo do google&lt;/a&gt; e cadastre-se no site &lt;a href=&quot;http://grupypb.net&quot;&gt;grupypb.net&lt;/a&gt;. Até o próximo encontro.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Skype derrubando conexão</title>
   <link href="http://igorsobreira.com/2009/05/21/skype-derrubando-conexao.html"/>
   <updated>2009-05-21T00:00:00-10:00</updated>
   <id>http://igorsobreira.com/2009/05/21/skype-derrubando-conexao</id>
   <content type="html">&lt;p&gt;A versão nova do Skype dava problemas com minha conexão, no OS X, simplesmente derrubava a conexão. Pra contornar o problema baixei uma versão mais antiga do skype e fiquei usando. Mas faltavam muitas novidades, como o vídeo.&lt;/p&gt;

&lt;p&gt;Agora eu resolvi &lt;em&gt;googlar&lt;/em&gt; mais um pouco e tentar resolver o problema. Descobri que não é com o Skype, mas com meu modem, um SpeadStream 4200, especificamente com o Universal Plug and Play (UPnP). Eu desabilitei o UPnP do meu modem e agora o Skype funciona.&lt;/p&gt;

&lt;p&gt;Depois dou uma estudada melhor como o UPnP funciona, e procuro uma solução menos &quot;gambiarrosa&quot; pra isso. Mas fica a dica pra quem tiver com o mesmo problema.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Suprimir DeprecationWarning</title>
   <link href="http://igorsobreira.com/2009/04/28/suprimir-deprecationwarning.html"/>
   <updated>2009-04-28T00:00:00-10:00</updated>
   <id>http://igorsobreira.com/2009/04/28/suprimir-deprecationwarning</id>
   <content type="html">&lt;p&gt;Algumas funcionalidades estão depreciadas no Python 2.6, e como alguns módulos externos ainda não estão atualizados, DeprecationWarnings são lançados. O &lt;a href=&quot;http://sourceforge.net/projects/mysql-python&quot;&gt;MySQLdb&lt;/a&gt;, por exemplo, lança o:&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;pycon&quot;&gt;&lt;span class=&quot;go&quot;&gt;DeprecationWarning: the sets module is deprecated&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;No meu caso, sempre que eu rodo o manage.py runserver no Django vejo esse warning, o que é bem chato. Para filtrá-lo, basta adicionar essas linhas no seu manage.py&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;python&quot;&gt;&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;warnings&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;warnings&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;simplefilter&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;#39;ignore&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ne&quot;&gt;DeprecationWarning&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;Isso já foi resolvido na versão beta do MySQLdb, porém o Django ainda não suporta essa versão, devido a muita coisa ter sido reescrita, mas suportará na versão 1.1, &lt;a href=&quot;http://groups.google.com/group/django-users/browse_thread/thread/c295c25b507cda57?hl=en&quot;&gt;segundo um dos core developers&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Só tenha cuidado pra não filtrar todos os warnings sempre, e deixar algum aviso importante passar despercebido.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Estruturas de dados do Django</title>
   <link href="http://igorsobreira.com/2009/04/15/estruturas-de-dados-do-django.html"/>
   <updated>2009-04-15T00:00:00-10:00</updated>
   <id>http://igorsobreira.com/2009/04/15/estruturas-de-dados-do-django</id>
   <content type="html">&lt;p&gt;O &lt;a href=&quot;http://djangoproject.com/&quot;&gt;Django&lt;/a&gt; tem um módulo com algumas estruturas de dados bem úteis, que ele usa internamente. Fica em &lt;a href=&quot;http://code.djangoproject.com/browser/django/trunk/django/utils/datastructures.py&quot;&gt;django.utils.datastructures&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Uma delas é a &lt;a href=&quot;http://code.djangoproject.com/browser/django/trunk/django/utils/datastructures.py#L53&quot;&gt;SortedDict&lt;/a&gt;, como o nome mesmo já diz, é um dicionário que mantém as chaves ordenadas. Já vi muita gente perguntando como ordenar os itens de um dicionário, taí um jeito.&lt;/p&gt;

&lt;p&gt;Ele faz isso herdando de dict e mantendo uma lista interna (keyOrder) com a ordem real das chaves. Não é algo complicado de se fazer, mas já ter lá pronta pra usar é uma mão na roda. O dicionários de campos (self.fields) dos formulários do Django são instâncias de SortedDict, por exemplo.&lt;/p&gt;

&lt;p&gt;Outra bem interessante é a &lt;a href=&quot;http://code.djangoproject.com/browser/django/trunk/django/utils/datastructures.py#L170&quot;&gt;MultiValueDict&lt;/a&gt;, um dicionário onde cada chave pode ter mais de um valor.&lt;/p&gt;

&lt;p&gt;Bem, fica a dica! Um bom começo, pra quem usa Django, pra começar a dar uma fuçada nos fontes.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Python weakref</title>
   <link href="http://igorsobreira.com/2009/04/14/python-weakref.html"/>
   <updated>2009-04-14T00:00:00-10:00</updated>
   <id>http://igorsobreira.com/2009/04/14/python-weakref</id>
   <content type="html">&lt;p&gt;Existe um módulo bem interessante na biblioteca padrão do Python que eu não conhecia até pouco tempo atrás, o &lt;a href=&quot;http://docs.python.org/library/weakref.html&quot;&gt;weakref&lt;/a&gt;. Ele serve pra manter uma &quot;referência fraca&quot; para um objeto. Mas o que seria isso?
Uma &lt;em&gt;weak reference&lt;/em&gt; não é suficiente para manter o objeto na memória, então se só existir esse tipo de referência para o objeto, o coletor de lixo vai destruí-lo.&lt;/p&gt;

&lt;p&gt;Isso é interessante pra evitar um alto consumo de memória com objetos muito grandes que não deveriam mais estar vivos. Um problema que pode acontecer usando o padrão de projeto &lt;a href=&quot;http://en.wikipedia.org/wiki/Observer_pattern&quot;&gt;Observer&lt;/a&gt; (&lt;del&gt;mal implementado&lt;/del&gt;), por exemplo .&lt;/p&gt;

&lt;p&gt;Um exemplo&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;pycon&quot;&gt;&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Foo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;object&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;... &lt;/span&gt;  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;say_hello&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;print&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;#39;say hello&amp;#39;&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;... &lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Foo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;say_hello&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;say hello&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;r&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;weakref&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ref&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;&lt;code&gt;r&lt;/code&gt; é uma referência fraca para o objeto a&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;pycon&quot;&gt;&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;r&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;is&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;True&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;r&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;say_hello&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;say hello&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;del&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;gc&lt;/span&gt; &lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;collect&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;collect&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;    &lt;span class=&quot;c&quot;&gt;# forçando a coleta de lixo&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;0&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;print&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;r&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;None&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;Já existem classes úteis que usam weak references: WeakKeyDictionary e WeakValueDictionary. Vale a pena dar uma olhada na documentação:&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://docs.python.org/library/weakref.html&quot;&gt;http://docs.python.org/library/weakref.html&lt;/a&gt;&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Customizando o prompt interativo do Python</title>
   <link href="http://igorsobreira.com/2009/03/12/customizando-o-prompt-interativo-do-python.html"/>
   <updated>2009-03-12T00:00:00-10:00</updated>
   <id>http://igorsobreira.com/2009/03/12/customizando-o-prompt-interativo-do-python</id>
   <content type="html">&lt;p&gt;Acredito que todo desenvolvedor que usa Python já deve ter o &lt;a href=&quot;http://ipython.scipy.org/moin/&quot;&gt;ipython&lt;/a&gt; instalado. É uma shell interativa que traz várias vantagens sob a que vem na instalação padrão do Python. Uma delas é autocompleta usando tabs.&lt;/p&gt;

&lt;p&gt;Mas tem como configurar a shell padrão pra autocomplete com tabs, histórico (com seta pra cima), ou o que mais você quiser.&lt;/p&gt;

&lt;p&gt;Antes do interpretador iniciar, ele lê a variável de ambiente &lt;a href=&quot;http://docs.python.org/using/cmdline.html#envvar-PYTHONSTARTUP&quot;&gt;PYTHONSTARTUP&lt;/a&gt;, e executa o conteúdo do arquivo pra onde ela aponta. Lá, você pode configurar algumas preferências pra o prompt.&lt;/p&gt;

&lt;p&gt;Primeiro baixe esse arquivo: &lt;a href=&quot;http://pypi.python.org/pypi/pbp.scripts&quot;&gt;pbp.scripts&lt;/a&gt;.
É um conjunto de códigos usados no livro &lt;a href=&quot;http://www.amazon.com/Expert-Python-Programming-practices-distributing/dp/184719494X&quot;&gt;Expert Python Programming&lt;/a&gt;,
de onde eu tirei essa dica.&lt;/p&gt;

&lt;p&gt;Dentro desse pacote, tem o script pythonstartup.py. Renomei ele para .pythonstartup e copie para sua pasta home. No meu caso, no OS X, ficou: /Users/igorsobreira/.pythonstartup&lt;/p&gt;

&lt;p&gt;Depois é só setar a variável de ambiente apontando pra ele&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;$ export PYTHONSTARTUP=/Users/igorsobreira/.pythonstartup
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Para esse export ser executado sempre que a shell do seu usuário iniciar, no OS X pode adicionar no arquivo &lt;code&gt;~/.profile&lt;/code&gt;. No linux, &lt;code&gt;~/.bash_profile&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Agora é só testar:&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;pycon&quot;&gt;&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;sys&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;sys&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;tab&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;tab&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;



</content>
 </entry>
 
 <entry>
   <title>MySQL-python no Mac OS</title>
   <link href="http://igorsobreira.com/2008/12/29/mysql-python-no-mac-os.html"/>
   <updated>2008-12-29T00:00:00-10:00</updated>
   <id>http://igorsobreira.com/2008/12/29/mysql-python-no-mac-os</id>
   <content type="html">&lt;p&gt;&lt;a href=&quot;http://sourceforge.net/projects/mysql-python/&quot;&gt;MySQL-python&lt;/a&gt; é o módulo que o Python usa para se conectar a bancos MySQL. Tive um probleminha pra instalar ele aqui no Mac OS, mas é um bug conhecido, e já tem a solução no &lt;a href=&quot;http://www.google.com&quot;&gt;oráculo&lt;/a&gt;. Mas vou documentar aqui também.&lt;/p&gt;

&lt;p&gt;Primeiro, &lt;a href=&quot;http://sourceforge.net/project/showfiles.php?group_id=22307&amp;package_id=15775&amp;release_id=491012&quot;&gt;baixar o  pacote&lt;/a&gt;. E descompactar:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;$ tar xvzf MySQL-python-1.2.2.tar.gz
$ cd MySQL-python-1.2.2
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Se você não tiver o &lt;code&gt;mysql_config&lt;/code&gt; no PATH, é preciso editar o setup-posix.py, onde tiver&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;mysql_config.path = &quot;mysql_config&quot;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;mudar para o caminho completo&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;mysql_config.path = &quot;/usr/local/mysql/bin/mysql_config&quot;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Caso ainda retorne o erro:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;In file included from /usr/local/mysql/include/mysql.h:47,
                 from _mysql.c:40:
/usr/include/sys/types.h:92: error: duplicate 'unsigned'
/usr/include/sys/types.h:92: error: two or more data types in declaration specifiers
error: command '/usr/bin/gcc-4.0' failed with exit status 1
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Basta comentar, no arquivo _mysql.c, a linha&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;#define uint unsigned int
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Agora é só instalar&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;$ sudo python setup.py install
&lt;/code&gt;&lt;/pre&gt;
</content>
 </entry>
 
 <entry>
   <title>Properties no Python 2.6</title>
   <link href="http://igorsobreira.com/2008/12/28/properties-no-python-26.html"/>
   <updated>2008-12-28T00:00:00-10:00</updated>
   <id>http://igorsobreira.com/2008/12/28/properties-no-python-26</id>
   <content type="html">&lt;p&gt;Uma das features que eu mais gosto em Python são as &lt;a href=&quot;http://docs.python.org/library/functions.html#property&quot;&gt;properties&lt;/a&gt;. Elas são possíveis graças aos &lt;a href=&quot;http://docs.python.org/reference/datamodel.html#implementing-descriptors&quot;&gt;descriptors&lt;/a&gt;, mas isso é assunto pra outro post. E na versão 2.6, as properties ganharam 3 atributos: getter, setter e deleter. Veja mais &lt;a href=&quot;http://docs.python.org/dev/whatsnew/2.6.html#other-language-changes&quot;&gt;aqui&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Primeiro, vou mostrar como elas sempre funcionaram. Ai vai um exemplo &quot;dummy&quot;, não levem em conta a funcionalidade em si (sou péssimo em exemplos):&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;python&quot;&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Conta&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;object&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;__init__&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;saldo&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;0.0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
        &lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;saldo&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;saldo&lt;/span&gt;
    
    &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;depositar&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;valor&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;valor&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
            &lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;saldo&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;valor&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;True&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;False&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;Certo, uma classe Conta, onde eu posso depositar um valor, que incrementa meu 'saldo'. Mas como ver o saldo? Os &quot;Javeiros&quot; de plantão perguntariam logo: &quot;Onde está o getter do saldo?!&quot;. E eu respondo: &quot;Não tem :-)&quot;. Simplesmente porque não precisa. Se você quiser ver o saldo, acesse o atributo direto:&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;pycon&quot;&gt;&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;c&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Conta&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mf&quot;&gt;100.00&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;print&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;saldo&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;100.00&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;depositar&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mf&quot;&gt;20.00&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;print&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;saldo&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;120.00&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;Mas isso não fere o encapsulamento? Um dos princípios básico da OO!?! É aí que entra as properties. Em Python, atributos são acessados diretamente, só se você precisar fazer algo quando acessá-lo, ai você cria um getter, e transforma o atributo numa property. Vejamos como ficaria a classe Conta:&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;python&quot;&gt;&lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;datetime&lt;/span&gt; &lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;datetime&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Conta&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;object&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;__init__&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;saldo&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;0.0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
        &lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;_saldo&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;saldo&lt;/span&gt;
        &lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;_ultimo_acesso&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;None&lt;/span&gt;
    
    &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;depositar&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;valor&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;valor&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
            &lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;_saldo&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;valor&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;True&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;False&lt;/span&gt;
    
    &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;_get_saldo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
        &lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;_ultimo_acesso&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;datetime&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;now&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;_saldo&lt;/span&gt;
    
    &lt;span class=&quot;n&quot;&gt;saldo&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;property&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;_get_saldo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;Agora, ao acessar a 'property' saldo, estaremos chamando o método &lt;code&gt;_get_saldo()&lt;/code&gt;. O cliente da classe continua com a mesma API. Veja que eu usei um underline (_) na frente dos atributos, isso em Python é uma convenção, pra informar que o atributo é &quot;privado&quot;, &lt;a href=&quot;/2010/09/16/difference-between-one-underline-and-two-underlines-in-python.html&quot;&gt;já que não existem atributos realmente privados&lt;/a&gt;.&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;pycon&quot;&gt;&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;c&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Conta&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mf&quot;&gt;100.00&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;print&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;saldo&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;100.00&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;print&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;_ultimo_acesso&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;2008-12-28 14:30:05.598644&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;Ou seja, getters e setters? Somente quando precisar. Confesso que depois de conhecer essa feature, dá dor na vista ler códigos em Java, PHP, etc...com vários getX, getY, getZ somente com uma linha retornando o atributo equivalente.&lt;/p&gt;

&lt;p&gt;Uma property é um descriptor que &lt;em&gt;conecta&lt;/em&gt; funções ao acesso a um determinado atributo. Tem a seguinte assinatura:&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;python&quot;&gt;&lt;span class=&quot;nb&quot;&gt;property&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;fget&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;None&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;fset&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;None&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;fdel&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;None&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;doc&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;None&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;Vamos criar um setter para a classe acima:&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;python&quot;&gt;&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;_set_saldo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;novo_saldo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;novo_saldo&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;_saldo&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;novo_saldo&lt;/span&gt;

&lt;span class=&quot;c&quot;&gt;# a property agora seria&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;saldo&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;property&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;_get_saldo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_set_saldo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;Aqui vai o código na íntegra, com alguns doctests: &lt;a href=&quot;/assets/uploads/conta.py&quot;&gt;conta.py&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Sim, mas o que mudou no Python 2.6? Veja como eu poderia criar o getter e setter:&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;python&quot;&gt;&lt;span class=&quot;nd&quot;&gt;@property&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;saldo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
    &lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;_ultimo_acesso&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;datetime&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;now&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;_saldo&lt;/span&gt;

&lt;span class=&quot;nd&quot;&gt;@saldo.setter&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;saldo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;novo_saldo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;novo_saldo&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;_saldo&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;novo_saldo&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;Aqui está o código moficado: &lt;a href=&quot;/assets/uploads/conta2.py&quot;&gt;conta2.py&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Referências:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;http://www.python.org/download/releases/2.2/descrintro/&quot;&gt;Unifying types and classes in Python 2.2&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://users.rcn.com/python/download/Descriptor.htm&quot;&gt;How-To Guide for Descriptors&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</content>
 </entry>
 
 <entry>
   <title>mod_wsgi no OSX</title>
   <link href="http://igorsobreira.com/2008/12/16/mod_wsgi-no-osx.html"/>
   <updated>2008-12-16T00:00:00-10:00</updated>
   <id>http://igorsobreira.com/2008/12/16/mod_wsgi-no-osx</id>
   <content type="html">&lt;p&gt;Finalmente consegui botar o &lt;a href=&quot;http://code.google.com/p/modwsgi/&quot;&gt;mod_wsgi&lt;/a&gt; pra funcionar no OSX, usando o Python 2.6.
Tive problemas compilando na mão com o Apache que já vem instalado no sistema, então resolvi instalar tudo com &lt;a href=&quot;www.macports.org/&quot;&gt;macports&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Primeiro instalei o Python 2.5.2, depois o Python 2.6.1, deixando como default o 2.6.1. Meu medo era o comando python_select abaixo sobrescrever o python default do sistema (o /usr/bin/python), e dar problemas internos, mas o /usr/bin/python continua lá, com o 2.5.1 &quot;mechido&quot; pela Apple :-).&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;$ sudo port install python25
$ sudo port install python26
$ sudo python_select python26
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Pronto, agora instalar o Apache, também pelo macports&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;$ sudo port install apache2
$ sudo launchctl load -w /Library/LaunchDaemons/org.macports.apache2.plist
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Se você estava usando o Apache que já vem no sistema (como eu), não esqueça de desativar em System Preferences -&gt; Sharing.&lt;/p&gt;

&lt;p&gt;Agora pra instalar o mod_wsgi, eu alterei algumas coisas no Portfile, já que a versão que tava lá era antiga, e pedia o Python 2.4. Seguei abaixo meu Portfile:&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://arquivos.igorsobreira.com/python/Portfile&quot;&gt;/opt/local/var/macports/sources/rsync.macports.org/release/ports/www/mod_wsgi/Porfile&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;É isso, um script simples pra testar se tudo tá funcionando:&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;python&quot;&gt;&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;application&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;environ&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;start_response&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;start_response&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;#39;200 OK&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;  &lt;span class=&quot;p&quot;&gt;[(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;#39;Content-type&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;#39;text/plain&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)])&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;#39;Ola mundo!&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;Salve em /opt/local/apache2/htdocs/test.wsgi.
Edite seu /opt/local/apache2/conf/httpd.conf e adicione a linha:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;WSGIScriptAlias /wsgi/test /opt/local/apache2/htdocs/test.wsgi
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Basta reiniciar o Apache&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;$ sudo /opt/local/apache2/bin/apachectl restart
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;E acessar a url &lt;a href=&quot;/localhost/wsgi/test&quot;&gt;/localhost/wsgi/test&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Tive problemas tentando compilar o mod_wsgi (com macports) com o python 2.6, e a versão padrão do sistema (com python_select) sendo o 2.5, dava uns erros com a função start_response. Mas agora tudo (aparentemente) funciona bem.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Django 1.0!</title>
   <link href="http://igorsobreira.com/2008/08/31/django-10.html"/>
   <updated>2008-08-31T00:00:00-10:00</updated>
   <id>http://igorsobreira.com/2008/08/31/django-10</id>
   <content type="html">&lt;p&gt;A versão &lt;a href=&quot;http://www.djangoproject.com/download/&quot;&gt;1.0 do Django&lt;/a&gt; acaba de sair, veja a notícia do lançamento &lt;a href=&quot;http://www.djangoproject.com/weblog/2008/sep/03/1/&quot;&gt;aqui&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Se tiver migrando de uma versão mais antiga, ou até mesmo do trunk um pouco desatualizado, veja &lt;a href=&quot;http://code.djangoproject.com/wiki/BackwardsIncompatibleChanges&quot;&gt;o que quebrou compatibilidade&lt;/a&gt;, e aproveite! :-)&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Auto-complete no Django</title>
   <link href="http://igorsobreira.com/2008/06/03/auto-complete-no-django.html"/>
   <updated>2008-06-03T00:00:00-10:00</updated>
   <id>http://igorsobreira.com/2008/06/03/auto-complete-no-django</id>
   <content type="html">&lt;p&gt;Existe um script no diretório &lt;a href=&quot;http://code.djangoproject.com/browser/django/trunk/extras&quot;&gt;extras&lt;/a&gt; do Django que oferece auto-complete nos scripts &lt;code&gt;django-admin.py&lt;/code&gt; e no &lt;code&gt;manage.py&lt;/code&gt;, é o &lt;a href=&quot;http://code.djangoproject.com/browser/django/trunk/extras/django_bash_completion&quot;&gt;django_bash_completion&lt;/a&gt;.
Para usar basta adicionar a seguinte linha no seu arquivo &lt;code&gt;~/.bashrc&lt;/code&gt;&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;. /home/igor/django-trunk/extras/django_bash_completion
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;substituindo pelo seu diretório do django. Começará a funcionar quando você se logar novamente.&lt;/p&gt;

&lt;p&gt;Eu utilizo a versão do trunk, não sei se esse escript vem no tarball da versão 0.96, provavelmente sim.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Palestra sobre Django no ECD</title>
   <link href="http://igorsobreira.com/2008/05/29/palestra-sobre-django-no-ecd.html"/>
   <updated>2008-05-29T00:00:00-10:00</updated>
   <id>http://igorsobreira.com/2008/05/29/palestra-sobre-django-no-ecd</id>
   <content type="html">&lt;p&gt;Hoje eu dei uma palestra sobre Django, no &lt;a href=&quot;encontro.comunicacaodigital.org&quot;&gt;II Encontro Comunicação Digital&lt;/a&gt;, uma rápida introdução, seguida de um exemplo prático, onde eu fiz lá uma aplicação simples pra controle de gastos.&lt;/p&gt;

&lt;p&gt;Os slides e o código fonte do exemplo estão &lt;a href=&quot;/apresentacoes/&quot;&gt;aqui&lt;/a&gt;. Espero que seja útil.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Novo usuário Gentoo!</title>
   <link href="http://igorsobreira.com/2008/04/06/novo-usuario-gentoo.html"/>
   <updated>2008-04-06T00:00:00-10:00</updated>
   <id>http://igorsobreira.com/2008/04/06/novo-usuario-gentoo</id>
   <content type="html">&lt;p&gt;Sempre fui usuário Ubuntu, porém meu &quot;sempre&quot; não é lá grande coisa já que eu uso Linux a pouco mais de 2 anos. Testei um pouco o Fedora e OpenSuse também, mas o Ubuntu foi o que gostei mais, o velho &quot;apt-get&quot; é muito bom!
Até conhecer o emerge....&lt;/p&gt;

&lt;p&gt;Pra mim uma boa distro era aquela fácil de usar, que já vem tudo pronto. Tem coisa mais fácil que instalar um Ubuntu? Em meia hora você tem um sistema completo rodando. O único problema que cheguei a ter foi com wireless, mas as versões mais novas já detectavam direto.&lt;/p&gt;

&lt;p&gt;Na ultima versão, o Ubuntu Gutsy Gibbon, 7.10, eu tive alguns probleminhas chatos que começaram a me incomodar. Como por exemplo a interface gráfica travava com frequencia(provavelmente por causa de minha placa de vídeo ATI). Somente o famoso &quot;ctrl + alt + backspace&quot; pra resolver. E começou a ficar um pouco lento também, vá lá que meu processador não é lá grande coisa (Intel Celerom 1.73GHz), mas acho que dava pra ficar melhor.&lt;/p&gt;

&lt;p&gt;Ai resolvi começar a usar o &lt;a href=&quot;http://www.gentoo.org/&quot;&gt;Gentoo&lt;/a&gt;. Sempre tive vontade de usar, mas a longa e trabalhosa instalação sempre me assustou um pouco. Não só pelo fato de ser &quot;difícil&quot;, mas ia tomar muito tempo e eu não tinha como ficar 2 dias sem meu computador.
Um dia desses comecei a dar uma lida no &lt;a href=&quot;http://www.gentoo.org/doc/en/handbook/index.xml&quot;&gt;Handbook&lt;/a&gt; e tomei coragem. Passei um final de semana configurando e compilando o kernel do Gentoo, e na segunda tava &quot;pronto&quot;. Gentoo 2007.0, Kernel 2.6.24-gentoo-r3 e KDE 3.5. Mas ainda faltava atualizar pra o Python 2.5, wireless, placa de som e instalar muitos aplicativos.&lt;/p&gt;

&lt;p&gt;Depois que comecei a usar, bateu o arrependimento: &quot;Por que não instalei antes?!&quot;. Nunca vi meu computador tão rápido. O &lt;a href=&quot;http://www.gentoo.org/doc/en/handbook/handbook-x86.xml?part=2&amp;chap=1&quot;&gt;portage&lt;/a&gt; é muito bom! Na instalação você escolhe cada módulo que quer habilitar no Kernel, isso deixa o sistema enxuto e muito rápido, só com o essencial.&lt;/p&gt;

&lt;p&gt;Realmente dá um trabalho enorme pra instalar, pra quem tá acostumado com Ubuntu, Fedora, etc. Mas vale muito a pena, você começa a ter mais controle do sistema, entender melhor como as coisas funcionam (afinal você faz praticamente &quot;tudo&quot;).&lt;/p&gt;

&lt;p&gt;Ainda falta configurar algumas coisas, faz somente uma semana que tou usando, provavelmente ainda vou recompilar o kernel algumas vezes. Mas pra quem quer aprender mais sobre Linux e usar um sistema altamente customizado, acho que é a melhor solução.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Construtores e Destrutores em Python e PHP 5</title>
   <link href="http://igorsobreira.com/2008/03/14/construtores-e-destrutores-em-python-e-php-5.html"/>
   <updated>2008-03-14T00:00:00-10:00</updated>
   <id>http://igorsobreira.com/2008/03/14/construtores-e-destrutores-em-python-e-php-5</id>
   <content type="html">&lt;p&gt;Estava aqui brincando com Orientação a Objetos no PHP 5, e não pude evitar uma comparação com Python. Percebi que os contrutores e destrutores funcionam praticamente da mesma maneira, provavelmente na maioria das linguagens deve ser assim.&lt;/p&gt;

&lt;p&gt;Em Python o construtor é o método &lt;code&gt;__init__&lt;/code&gt; da sua classe. Bem, Mark Pilgrim, autor do &lt;a href=&quot;http://www.diveintopython.org/&quot; target=&quot;_blank&quot;&gt;Dive into Python&lt;/a&gt; tem uma opinião diferente:&lt;/p&gt;

&lt;blockquote&gt;&lt;p&gt;&quot;&lt;code&gt;__init__&lt;/code&gt; is called immediately after an instance of the class is created. It would be tempting but incorrect to call this the constructor of the class. It's tempting, because it looks like a constructor (by convention, &lt;code&gt;__init__&lt;/code&gt; is the first method defined for the class), acts like one (it's the first piece of code executed in a newly created instance of the class), and even sounds like one (“init” certainly suggests a constructor-ish nature). Incorrect, because the object has already been constructed by the time &lt;code&gt;__init__&lt;/code&gt; is called, and you already have a valid reference to the new instance of the class. But &lt;code&gt;__init__&lt;/code&gt; is the closest thing you're going to get to a constructor in Python, and it fills much the same role. &quot;&lt;/p&gt;&lt;/blockquote&gt;

&lt;p&gt;Eu concordo com essa explicação, mas aqui vou chamar &lt;code&gt;__init__&lt;/code&gt; de construtor mesmo.&lt;/p&gt;

&lt;p&gt;No Python funciona assim: você tem uma classe A, e uma classe B que herda de A. Se a class A tiver o método &lt;code&gt;__init__&lt;/code&gt;, mas a classe B não tiver, ao se instanciar a classe B, o interpretador vai procurar o construtor, não achando na classe atual, vai subindo para as classes base, chamando o primeiro que encontrar, no caso o da classe A. Confuso? Vejamos em código...&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;python&quot;&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;object&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;__init__&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;print&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;#39;estou na classe A&amp;#39;&lt;/span&gt;
    
&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;B&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;pass&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;Instanciando a classe B pra ver o que acontece:&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;pycon&quot;&gt;&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;b&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;B&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;estou na classe A&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;Ou seja, como a classe &lt;code&gt;B&lt;/code&gt; não tinha um construtor (&lt;code&gt;__init__&lt;/code&gt;), o interpretador foi subindo para as classes base até achar um, e não precisou ir muito longe, a classe &lt;code&gt;A&lt;/code&gt; já tinha.&lt;/p&gt;

&lt;p&gt;Mas se definirmos o &lt;code&gt;__init__&lt;/code&gt; na classe &lt;code&gt;B&lt;/code&gt;, ele vai ser executado e pára por ai:&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;python&quot;&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;object&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;__init__&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;print&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;#39;estou na classe A&amp;#39;&lt;/span&gt;
    
&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;B&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;__init__&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;print&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;#39;estou na classe B&amp;#39;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;E o resultado será&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;pycon&quot;&gt;&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;b&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;B&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;estou na classe B&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;Mas e se quisermos que o &lt;code&gt;__init__&lt;/code&gt; da classe &lt;code&gt;A&lt;/code&gt; fosse executado também? Nesse caso precisariamos chamá-lo explicitamente. Isso pode ser feito com a função &lt;code&gt;super()&lt;/code&gt;&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;python&quot;&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;object&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;__init__&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;print&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;#39;estou na classe A&amp;#39;&lt;/span&gt;
    
&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;B&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;__init__&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;print&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;#39;estou na classe B&amp;#39;&lt;/span&gt;
        &lt;span class=&quot;nb&quot;&gt;super&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;B&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;__init__&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;E o resultado será como esperado&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;pycon&quot;&gt;&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;b&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;B&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;estou na classe B&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;estou na classe A&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;blockquote&gt;&lt;p&gt;Atenção! Esse comportamento de construtores do Python acontece tanto para classes &lt;em&gt;old style&lt;/em&gt; quanto para classes &lt;em&gt;new style&lt;/em&gt;(que herdam de object). Porém o &lt;code&gt;super()&lt;/code&gt; só funciona com classes &lt;em&gt;new style&lt;/em&gt;. Uma sintaxe alternativa seria: &lt;code&gt;A.__init__(self)&lt;/code&gt;&lt;/p&gt;&lt;/blockquote&gt;

&lt;p&gt;A mesma coisa acontece com PHP 5 e seu construtor, o &lt;code&gt;__construct&lt;/code&gt;, vejamos o mesmo exemplo&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;php&quot;&gt;&lt;span class=&quot;x&quot;&gt;class A {&lt;/span&gt;
&lt;span class=&quot;x&quot;&gt;    public function __construct() {&lt;/span&gt;
&lt;span class=&quot;x&quot;&gt;        echo &amp;quot;Estou na classe A&amp;quot;;&lt;/span&gt;
&lt;span class=&quot;x&quot;&gt;    }&lt;/span&gt;
&lt;span class=&quot;x&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;x&quot;&gt;class B extends A { }&lt;/span&gt;

&lt;span class=&quot;x&quot;&gt;$b = new B;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;A saída do código abaixo será:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;Estou na classe A
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Mas e se definirmos o &lt;code&gt;__construct&lt;/code&gt; da classe B, como chamar o da class A também? Vejamos o exemplo:&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;php&quot;&gt;&lt;span class=&quot;x&quot;&gt;class A {&lt;/span&gt;
&lt;span class=&quot;x&quot;&gt;    public function __construct() {&lt;/span&gt;
&lt;span class=&quot;x&quot;&gt;        echo &amp;quot;Estou na classe A&amp;quot;;&lt;/span&gt;
&lt;span class=&quot;x&quot;&gt;    }&lt;/span&gt;
&lt;span class=&quot;x&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;x&quot;&gt;class B extends A {&lt;/span&gt;
&lt;span class=&quot;x&quot;&gt;    public function __construct() {&lt;/span&gt;
&lt;span class=&quot;x&quot;&gt;        parent::__construct();&lt;/span&gt;
&lt;span class=&quot;x&quot;&gt;        echo &amp;quot;Estou na classe B&amp;quot;;&lt;/span&gt;
&lt;span class=&quot;x&quot;&gt;    }&lt;/span&gt;
&lt;span class=&quot;x&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;x&quot;&gt;$b = new B;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;A saída será:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;Estou na classe A
Estou na classe B
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Em relação aos destrutores a idéia é a mesma. No Python seria o método &lt;code&gt;__del__&lt;/code&gt;, e no PHP 5 o &lt;code&gt;__destruct&lt;/code&gt;.
Um exemplo com Python:&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;python&quot;&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;object&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;__init__&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;print&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;#39;nascendo...&amp;#39;&lt;/span&gt;
    
    &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;__del__&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;print&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;#39;morrendo........&amp;#39;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;Testando...&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;pycon&quot;&gt;&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;nascendo...&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;del&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;morrendo........&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;
&lt;span class=&quot;gt&quot;&gt;Traceback (most recent call last):&lt;/span&gt;
  File &lt;span class=&quot;nb&quot;&gt;&amp;quot;&amp;lt;stdin&amp;gt;&amp;quot;&lt;/span&gt;, line &lt;span class=&quot;m&quot;&gt;1&lt;/span&gt;, in &lt;span class=&quot;n&quot;&gt;&amp;lt;module&amp;gt;&lt;/span&gt;
&lt;span class=&quot;gr&quot;&gt;NameError&lt;/span&gt;: &lt;span class=&quot;n&quot;&gt;name &amp;#39;a&amp;#39; is not defined&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;O mesmo exemplo em PHP:&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;php&quot;&gt;&lt;span class=&quot;x&quot;&gt;class A {&lt;/span&gt;
&lt;span class=&quot;x&quot;&gt;    public function __construct() {&lt;/span&gt;
&lt;span class=&quot;x&quot;&gt;        echo &amp;quot;Nascendo..&amp;quot;;&lt;/span&gt;
&lt;span class=&quot;x&quot;&gt;    }&lt;/span&gt;
&lt;span class=&quot;x&quot;&gt;    public function __destruct() {&lt;/span&gt;
&lt;span class=&quot;x&quot;&gt;        echo &amp;quot;Morrendo.....&amp;quot;;&lt;/span&gt;
&lt;span class=&quot;x&quot;&gt;    }&lt;/span&gt;
&lt;span class=&quot;x&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;x&quot;&gt;$a = new A;&lt;/span&gt;
&lt;span class=&quot;x&quot;&gt;unset($a);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;E a saida será:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;Nascendo..
Morrendo.....
&lt;/code&gt;&lt;/pre&gt;
</content>
 </entry>
 
 <entry>
   <title>Linux com cara de Windows</title>
   <link href="http://igorsobreira.com/2008/03/13/linux-com-cara-de-windows.html"/>
   <updated>2008-03-13T00:00:00-10:00</updated>
   <id>http://igorsobreira.com/2008/03/13/linux-com-cara-de-windows</id>
   <content type="html">&lt;p&gt;Pra quem tem vontade de migrar de windows pra Linux, mas acha o Linux &lt;i&gt;muito complicado&lt;/i&gt;, o &lt;a href=&quot;http://www.famelix.com.br/site/?langswitch_lang=pt&quot;&gt;Famelix&lt;/a&gt; é uma distribuição que facilita essa migração.&lt;/p&gt;

&lt;blockquote&gt;&lt;p&gt;Projeto de pesquisa iniciado em março de 2003, o Famelix GNU/Linux começou de maneira despretenciosa, com o objetivo de atender a sua comunidade local.&lt;/p&gt;

&lt;p&gt;Contudo, após mais de 3 anos e matéria traduzidas para mais de 40 línguas, o FAMELIX despertou o interesse mundial&lt;/p&gt;&lt;/blockquote&gt;
</content>
 </entry>
 
 <entry>
   <title>PIL - IOError - decoder jpeg not available</title>
   <link href="http://igorsobreira.com/2008/03/12/pil-ioerror-decoder-jpeg-not-available.html"/>
   <updated>2008-03-12T00:00:00-10:00</updated>
   <id>http://igorsobreira.com/2008/03/12/pil-ioerror-decoder-jpeg-not-available</id>
   <content type="html">&lt;p&gt;Eu estava com um problema com a &lt;a href=&quot;http://www.pythonware.com/products/pil/&quot;&gt;PIL&lt;/a&gt;, o módulo pra manipulação de imagens do python, sempre que tentava manipular uma imagem .jpg recebia esse erro:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;IOError: decoder jpeg not available
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;O problema é que tava faltando a &lt;i&gt;libjpeg&lt;/i&gt;, mas mesmo depois que eu instalei, nao tinha dado certo porque não tinha removido a instalação atual da PIL, então vou botar os passos aqui que finalmente  fez a coisa funcionar no Debian e Ubuntu.&lt;/p&gt;

&lt;p&gt;Primeiro remover a PIL que ta dando erro (como root):&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;# rm -rf /usr/lib/python2.5/site-packages/PIL
# rm -rf /usr/lib/python2.5/site-packages/PIL.pth 
# rm -rf Imaging-1.1.6  # onde quer que tenha instalado
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Agora instalar a libjpeg&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;# aptitude install libjpeg libjpeg-dev
# aptitude install  libfreetype6 libfreetype6-dev
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Baixar novamente a PIL, e instalar&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;# wget http://effbot.org/media/downloads/Imaging-1.1.6.tar.gz
# tar xvzf Imaging-1.1.6.tar.gz
# cd Imaging-1.1.6
# python setup.py build_ext -i
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Rodar os testes pra verificar se realmente não tem problemas&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;# python selftest.py 
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;e instalar&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;# python setup.py install
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;É isso ai.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Programando em Java no Gedit</title>
   <link href="http://igorsobreira.com/2008/03/11/programando-em-java-no-gedit.html"/>
   <updated>2008-03-11T00:00:00-10:00</updated>
   <id>http://igorsobreira.com/2008/03/11/programando-em-java-no-gedit</id>
   <content type="html">&lt;p&gt;Pois é, aqui estou eu programando em Java...esse período estou pagando uma cadeira de de POO, e &lt;s&gt;infelizmente&lt;/s&gt; é com Java. Na verdade meu curso é quase todo em Java.&lt;/p&gt;

&lt;p&gt;Mas eu uso o Gedit pra programar, e agora? Instalar o Eclipse ou ou alguma outra IDE? Por enquanto não. Existe um plugin no Gedit chamado &lt;a href=&quot;http://live.gnome.org/Gedit/ToolLauncherPlugin&quot;&gt;External Tools&lt;/a&gt;, que já vem nele, talvez precise habilitar em Edit -&gt; Preferences -&gt; Plugins. Com ele você pode executar códigos externos. Como por exemplo compilar e executar um arquivo em java.&lt;/p&gt;

&lt;p&gt;Pra compilar vá em Tools -&gt; External Tools, e adicione um novo, no comando adicione:&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;bash&quot;&gt;&lt;span class=&quot;nb&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;Compiling: &amp;quot;&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$GEDIT_CURRENT_DOCUMENT_PATH&lt;/span&gt;
javac &lt;span class=&quot;nv&quot;&gt;$GEDIT_CURRENT_DOCUMENT_PATH&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;Pode botar uma tecla de atalho se quiser.&lt;/p&gt;

&lt;p&gt;E pra executar o código, eu fiz um script em python, e adicionei no diretório: &lt;code&gt;~/.gedit/java_run.py&lt;/code&gt;. Segue o código &lt;strong&gt;Atualizado em 13/03&lt;/strong&gt;:&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;python&quot;&gt;&lt;span class=&quot;c&quot;&gt;#!/usr/bin/python&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;sys&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;os&lt;/span&gt; &lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;system&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;chdir&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;len&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;sys&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;argv&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;!=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;print&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;quot;Can&amp;#39;t run program&amp;quot;&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;sys&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;exit&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;chdir&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;sys&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;argv&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;command&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;#39;java &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;%s&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;#39;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;%&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;sys&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;argv&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;replace&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;#39;.java&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;#39;&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;system&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;command&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;E adicione um novo &quot;External Tool&quot; com o seguinte código:&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;bash&quot;&gt;&lt;span class=&quot;c&quot;&gt;#Runs a compiled Java source file.&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;Running: &amp;quot;&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$GEDIT_CURRENT_DOCUMENT_PATH&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;--------------------&amp;#39;&lt;/span&gt;
python ~/.gedit/java_run.py &lt;span class=&quot;nv&quot;&gt;$GEDIT_CURRENT_DOCUMENT_DIR&lt;/span&gt;  &lt;span class=&quot;nv&quot;&gt;$GEDIT_CURRENT_DOCUMENT_NAME&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;Pronto. Agora o Gedit é &lt;i&gt;quase&lt;/i&gt; uma IDE Java. :)&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>II Encontro do Comunicação Digital</title>
   <link href="http://igorsobreira.com/2008/03/10/ii-encontro-do-comunicacao-digital.html"/>
   <updated>2008-03-10T00:00:00-10:00</updated>
   <id>http://igorsobreira.com/2008/03/10/ii-encontro-do-comunicacao-digital</id>
   <content type="html">&lt;p&gt;Nos dias 28 a 30 de Maio, vai acontecer o &lt;a href=&quot;http://encontro.comunicacaodigital.org/&quot;&gt;II Encontro do Comunicação Digital&lt;/a&gt;, no CEFET-PB, João Pessoa-PB. Esse é um evento anual, e esse ano será a segunda edição.&lt;/p&gt;

&lt;p&gt;O &lt;a href=&quot;http://www.comunicacaodigital.org/&quot;&gt;Núcleo Comunicação Digital&lt;/a&gt; começou com um grupo de alunos voluntários que usavam e defendiam o software livre, principalmente o Linux, e decidiram se juntar para divulgá-lo. Além dessa idéia, de difusão do Linux, linguagens de programação opensource, etc, também veio a idéia de dividir conhecimento, criar a apoiar projetos de pesquisa, organizar eventos, ministrar palestras, cursos, grupos de estudo, etc.&lt;/p&gt;

&lt;p&gt;O primeiro evento, realizado em Abril de 2007 foi um sucesso, com várias palestras e workshops, e foi muito elogiado pelos congressistar, ministrantes e profissionais que participaram. Veja mais detalhes e fotos &lt;a href=&quot;http://www.comunicacaodigital.org/wiki/index.php?title=I_Encontro_do_Comunica%C3%A7%C3%A3o_Digital&quot;&gt;aqui.&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Esse ano o evento traz algumas novidades, como a apresentação de Postêrs, Mesas Redondas, e um processo de inscrição e submissão de palestras totalmente online e automatizado. Além das palestras e workshops, cujo período de submissão ja está aberto.
Aliás, não poderia deixar de falar, o site do evento foi feito em Django! :o)&lt;/p&gt;

&lt;p&gt;Esperamos que esse ano o número de participantes seja ainda maior. Participe, &lt;a href=&quot;http://encontro.comunicacaodigital.org/inscricoes/&quot;&gt;inscreva-se&lt;/a&gt; ou &lt;a href=&quot;http://encontro.comunicacaodigital.org/trabalhos/&quot;&gt;submeta um trabalho.&lt;/a&gt;&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Mensagens para os usuários no Django</title>
   <link href="http://igorsobreira.com/2008/02/13/mensagens-para-os-usuarios-no-django.html"/>
   <updated>2008-02-13T00:00:00-10:00</updated>
   <id>http://igorsobreira.com/2008/02/13/mensagens-para-os-usuarios-no-django</id>
   <content type="html">&lt;p&gt;Ultimamente tenho usado muito a &lt;a href=&quot;http://www.djangoproject.com/documentation/authentication/&quot;&gt;aplicação de autenticação do Django&lt;/a&gt;. Mas não estava muito satisfeito com o &lt;a href=&quot;http://www.djangoproject.com/documentation/authentication/#messages&quot;&gt;sistema de mensagens&lt;/a&gt; para os usuários que é oferecido. Na verdade a intenção é ser realmente bem simples, vejamos um exemplo:&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;python&quot;&gt;&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;alterar_foto&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;request&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
    &lt;span class=&quot;c&quot;&gt;# executa o código da view aqui....&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;request&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;user&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;message_set&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;create&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;message&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;u&amp;#39;Foto alterada&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;render_to_response&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;#39;usuarios/dados.html&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
                              &lt;span class=&quot;n&quot;&gt;context_instance&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;RequestContext&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;request&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;Foi adicionado uma mensagem para o usuário, assim podemos criar uma fila das últimas ações executadas pelo mesmo. Só que o método para acessar essas mensagens é o &lt;a href=&quot;http://code.djangoproject.com/browser/django/trunk/django/contrib/auth/models.py#L277&quot;&gt;get_and_delete_messages()&lt;/a&gt;:&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;python&quot;&gt;&lt;span class=&quot;n&quot;&gt;mensagens&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;user&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;get_and_delete_messages&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;e no template, assumido que esteja usando &lt;a href=&quot;http://www.djangoproject.com/documentation/templates_python/#subclassing-context-requestcontext&quot;&gt;RequestContext&lt;/a&gt;, ficaria assim:&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;django&quot;&gt;&lt;span class=&quot;x&quot;&gt;&amp;lt;ul&amp;gt;&lt;/span&gt;
&lt;span class=&quot;cp&quot;&gt;{%&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;message&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;messages&lt;/span&gt; &lt;span class=&quot;cp&quot;&gt;%}&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;x&quot;&gt;    &amp;lt;li&amp;gt;&lt;/span&gt;&lt;span class=&quot;cp&quot;&gt;{{&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;message&lt;/span&gt; &lt;span class=&quot;cp&quot;&gt;}}&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;&amp;lt;/li&amp;gt;&lt;/span&gt;
&lt;span class=&quot;cp&quot;&gt;{%&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;endfor&lt;/span&gt; &lt;span class=&quot;cp&quot;&gt;%}&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;x&quot;&gt;&amp;lt;/ul&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;pois o &lt;a href=&quot;http://www.djangoproject.com/documentation/templates_python/#subclassing-context-requestcontext&quot;&gt;RequestContext&lt;/a&gt; define no template a variável messages, que são as mensagens do usuário logado.
Mas como o próprio nome do método já diz, quando as mensagen são acessadas, elas são removidas. Eu não gostei muito disso, pelo fato de o usuário só poder ver as últimas ações uma única vez, além de que não tem um campo de data no model &lt;a href=&quot;http://code.djangoproject.com/browser/django/trunk/django/contrib/auth/models.py#L306&quot;&gt;Message&lt;/a&gt;, pra mostrar o dia e hora daquela ação.&lt;/p&gt;

&lt;p&gt;Daí decidi reinventar a roda, e fazer um sisteminha de mensagens com essas características.
Eu fiz as mensagens acopladas a um perfil que eu criei pra o usuário do django, e não vou detalhar como se criar um perfil para seu User, veja mais &lt;a href=&quot;http://www.djangobook.com/en/beta/chapter12/&quot;&gt;aqui(lá no final do capítulo)&lt;/a&gt; e &lt;a href=&quot;http://www.b-list.org/weblog/2006/jun/06/django-tips-extending-user-model/&quot;&gt;aqui&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Bem, basicamente é esse model:&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;python&quot;&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Action&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;models&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Model&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;user&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;models&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ForeignKey&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;UserProfile&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;action&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;models&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;CharField&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;max_length&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;200&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;pub_date&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;models&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;DateTimeField&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;auto_now_add&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;True&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;__unicode__&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;action&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Meta&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;ordering&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;#39;-pub_date&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,)&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;db_table&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;#39;auth_user_profile_action&amp;#39;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;Onde a classe &lt;code&gt;UserProfile&lt;/code&gt;, é minha classe que extende o User da aplicação contrib.auth do Django.
Daí eu adicionei um método na classe &lt;code&gt;UserProfile&lt;/code&gt;:&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;python&quot;&gt;&lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;django.contrib.auth.models&lt;/span&gt; &lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;User&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;UserProfile&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;models&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Model&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
    &lt;span class=&quot;c&quot;&gt;# meus campos extras&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;user&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;models&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ForeignKey&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;User&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;unique&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;True&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

    &lt;span class=&quot;c&quot;&gt;# mais alguns método aqui, como o __unicode__, a class Meta, class Admin, etc&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;keep_actions&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;maximum&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;actions&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;action_set&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;count&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;actions&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;maximum&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;extras&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;action_set&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;all&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;maximum&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;actions&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;extra&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;extras&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
                &lt;span class=&quot;n&quot;&gt;extra&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;delete&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;A intenção é a seguinte: sempre ter um número máximo de 'ultimas ações' do usuário, então esse método &lt;code&gt;keep_settings()&lt;/code&gt; recebe um parâmatro opcional(valor default é 10), que vai ser o número máximo de ações que ele vai permitir na tabela. É mais um método pra &quot;limpar&quot; as ações antigas.&lt;/p&gt;

&lt;p&gt;Um exemplo de uso:&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;python&quot;&gt;&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;adicionar_foto&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;request&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
    &lt;span class=&quot;c&quot;&gt;# codigo normal da view...&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;profile&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;request&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;user&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;get_profile&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;profile&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;action_set&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;create&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;action&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;u&amp;#39;Foto adicionada&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;profile&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;keep_actions&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;profile&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;save&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
    &lt;span class=&quot;c&quot;&gt;# termina a view normalmente....&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;Aí eu adiciono uma ação relacionada com meu usuário, e o método &lt;code&gt;keep_settings()&lt;/code&gt; vai garantir que terá no máximo 10 &quot;ultimas ações&quot;, caso tenha mais de 10, ele remove as mais antigas e deixa apenas as 10 mais recentes.&lt;/p&gt;

&lt;p&gt;E no template ficaria assim:&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;django&quot;&gt;&lt;span class=&quot;x&quot;&gt;&amp;lt;ul&amp;gt;&lt;/span&gt;
&lt;span class=&quot;cp&quot;&gt;{%&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;action&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;request.user.get_profile.action_set.all&lt;/span&gt; &lt;span class=&quot;cp&quot;&gt;%}&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;x&quot;&gt;    &amp;lt;li&amp;gt;&lt;/span&gt;&lt;span class=&quot;cp&quot;&gt;{{&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;action.pub_date&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;date&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;:&amp;#39;d/m/Y H:i&amp;#39;&lt;/span&gt; &lt;span class=&quot;cp&quot;&gt;}}&lt;/span&gt;&lt;span class=&quot;x&quot;&gt; - &lt;/span&gt;&lt;span class=&quot;cp&quot;&gt;{{&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;action&lt;/span&gt; &lt;span class=&quot;cp&quot;&gt;}}&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;&amp;lt;/li&amp;gt;&lt;/span&gt;
&lt;span class=&quot;cp&quot;&gt;{%&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;endfor&lt;/span&gt; &lt;span class=&quot;cp&quot;&gt;%}&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;x&quot;&gt;&amp;lt;/ul&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;Assim eu mostro a hora que a ação foi executada e deixo sempre um histórico de 10 ou mais últimas ações. Pra deletar todas poderia chamar o método &lt;code&gt;keep_actions(0)&lt;/code&gt; passando zero como parâmetro.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Envolva-se no mundo Django</title>
   <link href="http://igorsobreira.com/2008/01/31/envolva-se-no-mundo-django.html"/>
   <updated>2008-01-31T00:00:00-10:00</updated>
   <id>http://igorsobreira.com/2008/01/31/envolva-se-no-mundo-django</id>
   <content type="html">&lt;p&gt;Esse post vai pra quem ta começando no &lt;a href=&quot;www.djangoproject.com&quot;&gt;Django&lt;/a&gt;, e quer ficar mais ligado no que acontece por ai. Alguns sites, blogs listas de dicussão, pra aprender, tirar dúvidas e ver as novidades relacionadas ao Django.&lt;/p&gt;

&lt;p&gt;O mais recente é o &lt;a href=&quot;http://djangopeople.net&quot;&gt;Django People&lt;/a&gt;, que é como uma rede social de &lt;i&gt;djangers&lt;/i&gt;, onde você pode se cadastrar e encontrar outros &lt;i&gt;djangers&lt;/i&gt; por perto ou em qualquer lugar do mundo. No momento que escrevo esse post, o Brasil está em segundo lugar em número de pessoas cadastradas, com 89, perdendo apenas para os Estados Unidos. :D.
Eu também acompanho o feed do blog do criador do site, &lt;a href=&quot;http://simonwillison.net/&quot;&gt;Simon Willisons&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Tem o site da nossa comunidade nacional, &lt;a href=&quot;http://www.djangobrasil.org/&quot;&gt;Django Brasil&lt;/a&gt;. Lá tem o &lt;a href=&quot;http://www.djangobrasil.org/comunidade/&quot;&gt;agregado de blogs&lt;/a&gt; de vários desenvolvedores pelo Brasil que usam Django. E também o &lt;a href=&quot;http://www.djangobrasil.org/weblog/&quot;&gt;blog oficial&lt;/a&gt; do Django Brasil.
A &lt;a href=&quot;http://www.djangoproject.com/documentation/&quot;&gt;documentação oficial&lt;/a&gt; está sendo &lt;a href=&quot;http://groups.google.com/group/django-l10n-portuguese/&quot;&gt;traduzinda para o português&lt;/a&gt;.
Tem também o &lt;a href=&quot;http://www.amazon.com/gp/product/1590597257?ie=UTF8&amp;tag=jacobianorg-20&amp;linkCode=as2&amp;camp=1789&amp;creative=9325&amp;creativeASIN=1590597257&quot;&gt;DjangoBook&lt;/a&gt;, um livro que foi lançado recentemente, e está &lt;a href=&quot;http://www.djangobook.com/&quot;&gt;disponível online&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;O &lt;a href=&quot;http://www.djangosnippets.org/&quot;&gt;DjangoSnippets&lt;/a&gt; é muito bom, são &lt;i&gt;snippets&lt;/i&gt; que os desenvolvedores colocam pra comunidade. Sempre acho algo interessante aqui. Só sinto falta de uma caixinha de busca no site, mas se bem que toda vez que procuro algo lá por tag, linguagem, acabo esbarrando em alguma coisa boa!&lt;/p&gt;

&lt;p&gt;Está procurando emprego em Django? Ou desenvolvedores? Cadastre-se no &lt;a href=&quot;http://djangogigs.com/&quot;&gt;DjangoGigs&lt;/a&gt;!&lt;/p&gt;

&lt;p&gt;Você já tem um site feito em Django? Cadastre ele no &lt;a href=&quot;http://www.djangosites.org/latest/&quot;&gt;Django Sites&lt;/a&gt;, que já tem mais de 900 sites cadastrados! E coloque um &lt;a href=&quot;http://www.djangoproject.com/community/badges/&quot;&gt;logo do django&lt;/a&gt; no seu site também.&lt;/p&gt;

&lt;p&gt;Tem também alguns projetos legais de aplicações para seu projeto:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;http://code.google.com/p/django-diario/&quot;&gt; django-diario &lt;/a&gt;, é um weblog plugável&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://code.google.com/p/django-tagging/&quot;&gt; django-tagging &lt;/a&gt;, uma aplicação de tags genérica&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://code.google.com/p/django-photologue/&quot;&gt; django-photologue &lt;/a&gt;, uma galeria de fotos&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://code.google.com/p/django-gadgets/&quot;&gt; django-gadgets &lt;/a&gt;, para desenvolver &lt;A href=&quot;http://www.google.com/ig/directory?synd=open&quot;&gt;Google Gadgets&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;


&lt;p&gt;A pouco tempo tava procurando como reproduzir videos em flash nos sites, e achei dois links interessantes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;http://blog.go4teams.com/?p=56&quot;&gt; Video Blogging using Django and Flash(tm) Video (FLV) &lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.pyjax.net/blog/1/2007/09/28/django-template-tag-integrating-flash-based-flv-pl/&quot;&gt;A Django template tag for integrating a Flash based flv player&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;


&lt;p&gt;A &lt;a href=&quot;http://groups.google.com/group/django-brasil/&quot;&gt;lista de discussão&lt;/a&gt; é bem movimentada, felizmente a comunidade nacional de Django está crescendo muito. Participe no canal &lt;a href=&quot;irc://irc.freenode.net/django-br&quot;&gt;#django-br&lt;/a&gt; na &lt;a href=&quot;irc://irc.freenode.net&quot;&gt;Freenode&lt;/a&gt; também, e no &lt;a href=&quot;irc://irc.freenode.net/django&quot;&gt;#django&lt;/a&gt;.
Além das listas internacionais: &lt;a href=&quot;http://groups.google.com/group/django-users&quot;&gt;django-users&lt;/a&gt; e &lt;a href=&quot;http://groups.google.com/group/django-developers&quot;&gt;django-developers&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Não me lembro de mais links interessantes pra passar, caso alguem tenha mais, vou adorar adicionar no meu del.icio.us. :)&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Django no Jython</title>
   <link href="http://igorsobreira.com/2008/01/30/django-no-jython.html"/>
   <updated>2008-01-30T00:00:00-10:00</updated>
   <id>http://igorsobreira.com/2008/01/30/django-no-jython</id>
   <content type="html">&lt;p&gt;Django irá rodar no &lt;a href=&quot;http://wiki.python.org/jython/FrontPage&quot;&gt;Jython 2.5&lt;/a&gt;, que será sua próxima versão, compatível com a 2.5 atual do CPython.&lt;/p&gt;

&lt;p&gt;Atualmente ainda precisam de alguns &lt;i&gt;hacks&lt;/i&gt; pra funcionar, e ainda tem algumas funcionalidades &lt;i&gt;quebradas&lt;/i&gt;, como por exemplo o servidor de desenvolvimento tem que ser inicializado com &lt;code&gt;--noreload&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Veja mais detalhes:
&lt;a href=&quot;http://wiki.python.org/jython/DjangoOnJython&quot;&gt; DjangoOnJython &lt;/a&gt;
&lt;a href=&quot;http://www.infoq.com/news/2008/01/django_on_jython&quot;&gt; Python Web Framework on the JVM &lt;/a&gt;&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Conjuntos em Python - set e frozenset</title>
   <link href="http://igorsobreira.com/2008/01/20/conjuntos-em-python-set-e-frozenset.html"/>
   <updated>2008-01-20T00:00:00-10:00</updated>
   <id>http://igorsobreira.com/2008/01/20/conjuntos-em-python-set-e-frozenset</id>
   <content type="html">&lt;p&gt;Os conjuntos são um tipo de dados do python que nunca ouvi falar muito. Eu particularmente nunca usei, mas dando uma olhada agora vi que são muito interessantes.&lt;/p&gt;

&lt;p&gt;Uma coisa que eu precisei fazer ontem foi retirar dados repedidos de uma lista, e não existe um método de lista que faça isso. Já nos conjuntos isso é automático, não existem dados repetidos.&lt;/p&gt;

&lt;p&gt;A diferença entre &lt;b&gt;set&lt;/b&gt; e &lt;b&gt;frozenset&lt;/b&gt;, é que o primeiro é mutável, já o segunto não.
Criando um conjunto...&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;pycon&quot;&gt;&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;conjunto1&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;set&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;#39;12345&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;conjunto1&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;set([&amp;#39;1&amp;#39;, &amp;#39;3&amp;#39;, &amp;#39;2&amp;#39;, &amp;#39;5&amp;#39;, &amp;#39;4&amp;#39;])&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;Veja que é passado um tipo iterável para o set(nessa caso uma string), onde cada elemento vai ser um elemento do conjunto.&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;pycon&quot;&gt;&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;conjunto2&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;set&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;([&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;7&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;7&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;8&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;9&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;conjunto2&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;set([8, 9, 4, 7])&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;Veja que realmente ele não permite elementos repetidos.
Você deve ter percebido que os elementos não estão na mesma ordem que foram passados. Isso porquê conjuntos realmente não possuem nenhuma ordem. São &lt;b&gt;iteráveis&lt;/b&gt;, ou seja, podemos fazer &lt;code&gt;for x in meu_conjunto&lt;/code&gt;, &lt;code&gt;len(meu_conjunto)&lt;/code&gt;, &lt;code&gt;x in meu_conjunto&lt;/code&gt;. Mas como eles &lt;b&gt;não possuem ordem&lt;/b&gt;, não é permitido indexação, nem slicing, algo tipo &lt;code&gt;meu_conjunto[2:]&lt;/code&gt; está errado.&lt;/p&gt;

&lt;p&gt;Mas vamos a algumas operações entre conjuntos.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Está contido e contém&lt;/strong&gt;&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;pycon&quot;&gt;&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;conjunto1&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;issubset&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;conjunto2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;False&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;conjunto1&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;issubset&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;set&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;#39;123456789&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;True&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;Também podemos usar os operadores&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;pycon&quot;&gt;&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;conjunto1&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;set&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;#39;123456789&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;True&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;set&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;#39;123456789&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;conjunto1&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;True&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;&lt;strong&gt;União&lt;/strong&gt;&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;pycon&quot;&gt;&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;conjunto1&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;union&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;conjunto2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;set([4, 7, 8, 9, &amp;#39;1&amp;#39;, &amp;#39;3&amp;#39;, &amp;#39;2&amp;#39;, &amp;#39;5&amp;#39;, &amp;#39;4&amp;#39;])&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;conjunto1&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;conjunto2&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;set([4, 7, 8, 9, &amp;#39;1&amp;#39;, &amp;#39;3&amp;#39;, &amp;#39;2&amp;#39;, &amp;#39;5&amp;#39;, &amp;#39;4&amp;#39;])&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;&lt;strong&gt;Interseção&lt;/strong&gt;&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;pycon&quot;&gt;&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;set&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;#39;123&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;intersection&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;set&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;#39;345&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;set([&amp;#39;3&amp;#39;])&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;set&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;#39;123&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;set&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;#39;345&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;set([&amp;#39;3&amp;#39;])&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;&lt;strong&gt;Diferença&lt;/strong&gt;&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;pycon&quot;&gt;&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;set&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;#39;1234&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;difference&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;set&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;#39;3&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;set([&amp;#39;1&amp;#39;, &amp;#39;2&amp;#39;, &amp;#39;4&amp;#39;])&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;set&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;#39;1234&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;set&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;#39;34&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;set([&amp;#39;1&amp;#39;, &amp;#39;2&amp;#39;])&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;Operações entre sets e frozensets são permitidas, mas veja que a ordem em que eles aparecem importa&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;pycon&quot;&gt;&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;set&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;#39;234&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;frozenset&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;#39;45&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;set([&amp;#39;3&amp;#39;, &amp;#39;2&amp;#39;, &amp;#39;5&amp;#39;, &amp;#39;4&amp;#39;])&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;frozenset&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;#39;23&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;set&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;#39;567&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;frozenset([&amp;#39;3&amp;#39;, &amp;#39;2&amp;#39;, &amp;#39;5&amp;#39;, &amp;#39;7&amp;#39;, &amp;#39;6&amp;#39;])&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;Outra coisa importante, é que podemos passar iteráveis tanto na criação do set como nas operações usando os métodos. Mas as operações usando os operadores devem ser obrigatoriamente entre sets:&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;pycon&quot;&gt;&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;set&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;#39;234&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;union&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;([&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;6&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;set([&amp;#39;3&amp;#39;, &amp;#39;2&amp;#39;, &amp;#39;4&amp;#39;, 6, 5])&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;set&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;#39;234&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;gt&quot;&gt;Traceback (most recent call last):&lt;/span&gt;
  File &lt;span class=&quot;nb&quot;&gt;&amp;quot;&amp;lt;stdin&amp;gt;&amp;quot;&lt;/span&gt;, line &lt;span class=&quot;m&quot;&gt;1&lt;/span&gt;, in &lt;span class=&quot;n&quot;&gt;&amp;lt;module&amp;gt;&lt;/span&gt;
&lt;span class=&quot;gr&quot;&gt;TypeError: unsupported operand type(s) for |&lt;/span&gt;: &lt;span class=&quot;n&quot;&gt;&amp;#39;set&amp;#39; and &amp;#39;list&amp;#39;&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;Os sets, por serem mutáveis, também possuem métodos que adicionar e remover novos elementos. Como os frozensets são imutáveis, não possuem esse métodos&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;pycon&quot;&gt;&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;conjunto1&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;set&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;([&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;#39;a&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;#39;b&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;#39;c&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;#39;d&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;conjunto1&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;set([&amp;#39;a&amp;#39;, &amp;#39;c&amp;#39;, &amp;#39;b&amp;#39;, &amp;#39;d&amp;#39;])&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;conjunto1&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;update&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;set&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;#39;nada&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;conjunto1&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;set([&amp;#39;a&amp;#39;, &amp;#39;c&amp;#39;, &amp;#39;b&amp;#39;, &amp;#39;d&amp;#39;, &amp;#39;n&amp;#39;])&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;O &lt;code&gt;conjunto.update(outro_conjunto)&lt;/code&gt;, atualiza &lt;code&gt;conjunto&lt;/code&gt; adicionando os elementos de &lt;code&gt;outro_conjunto&lt;/code&gt;. Tem também os métodos &lt;code&gt;set.add(x)&lt;/code&gt;, &lt;code&gt;set.remove(x)&lt;/code&gt;, &lt;code&gt;set.pop()&lt;/code&gt;, &lt;code&gt;set.clear()&lt;/code&gt;. Além do &lt;code&gt;set.discard(x)&lt;/code&gt;, que só remove o elemento se ele existir, diferente do &lt;code&gt;remove()&lt;/code&gt; que retorna &lt;code&gt;KeyError&lt;/code&gt; caso o elemento não exista.&lt;/p&gt;

&lt;p&gt;O exemplo que eu citei no começo, de retirar dados repetidos de uma lista poderia ter sido feito assim:&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;pycon&quot;&gt;&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;numeros&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;6&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;list&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;set&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;numeros&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;[1, 2, 3, 5, 6]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;Simples não?&lt;/p&gt;

&lt;p&gt;Veja mais detalhes sobre conjuntos &lt;a href=&quot;http://docs.python.org/lib/types-set.html&quot;&gt;aqui&lt;/a&gt;&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Novo blog em Django</title>
   <link href="http://igorsobreira.com/2008/01/15/novo-blog-em-django.html"/>
   <updated>2008-01-15T00:00:00-10:00</updated>
   <id>http://igorsobreira.com/2008/01/15/novo-blog-em-django</id>
   <content type="html">&lt;p&gt;Nos últimos meses eu tenho brincado com &lt;a href=&quot;http://www.djangoproject.com&quot; target=&quot;_blank&quot;&gt;Django&lt;/a&gt;, e estou achando muito bom, o desenvolvimento é bem ágil, afinal é Python! Testei o &lt;a href=&quot;http://turbogears.org/&quot; target=&quot;_blank&quot;&gt;TurboGears&lt;/a&gt; também no começo, mas Django me atraiu mais...&lt;/p&gt;

&lt;p&gt;Acabei de terminar esse blog, feito em Django. Por isso vou descontinuar o &lt;a href=&quot;http://defpython.blogspot.com&quot; target=&quot;_blank&quot;&gt;defpython&lt;/a&gt;, vou deixar ele lá pois tem uns artigos legais, mas só vou atualizar esse aqui agora. E outra coisa que eu achava meio chato, era que o defpython tinha a finalidade de falar sobre Python, então eu evitava postar sobre outros assuntos, outras linguagens, etc. Mas aqui vai ter de tudo um pouco, com um feed específico pra cada categoria também.&lt;/p&gt;

&lt;p&gt;Por enquanto é só. Pra quem ainda não conhecia Django, o pessoal da comunidade &lt;a href=&quot;http://www.djangobrasil.org/&quot; target=&quot;_blank&quot;&gt;Django Brasil&lt;/a&gt; está fazendo um ótimo trabalho traduzinho a documentação oficial, é o &lt;a href=&quot;http://www.djangobrasil.org/documentacao/&quot;&gt;melhor lugar&lt;/a&gt; pra começar.&lt;/p&gt;
</content>
 </entry>
 
 
</feed>