<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>learning python &#187; python</title>
	<atom:link href="http://www.learningpython.com/tag/python/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.learningpython.com</link>
	<description>one man's journey into python...</description>
	<lastBuildDate>Mon, 26 Apr 2010 01:21:51 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=abc</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>Introducing Descriptors and Properties</title>
		<link>http://www.learningpython.com/2010/04/25/introducing-descriptors-and-properties/</link>
		<comments>http://www.learningpython.com/2010/04/25/introducing-descriptors-and-properties/#comments</comments>
		<pubDate>Mon, 26 Apr 2010 01:21:51 +0000</pubDate>
		<dc:creator>selsine</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[descriptors]]></category>
		<category><![CDATA[properties]]></category>
		<category><![CDATA[python]]></category>
		<category><![CDATA[Python Magazine]]></category>

		<guid isPermaLink="false">http://www.learningpython.com/?p=186</guid>
		<description><![CDATA[
			
				
			
		
Note: This article was first published the May 2008 issue of Python Magazine
Introducing Descriptors and Properties
Mark Mruss
New-style classes were introduced to Python with the release of Python 2.2. And with these new-style classes came descriptors and properties. This article will introduce the descriptor protocol, descriptors, and properties.
Introduction
New-style classes were introduced to Python with the release [...]]]></description>
			<content:encoded><![CDATA[<div class="tweetmeme_button" style="float: right; margin-left: 10px;">
			<a href="http://api.tweetmeme.com/share?url=http%3A%2F%2Fwww.learningpython.com%2F2010%2F04%2F25%2Fintroducing-descriptors-and-properties%2F"><br />
				<img src="http://api.tweetmeme.com/imagebutton.gif?url=http%3A%2F%2Fwww.learningpython.com%2F2010%2F04%2F25%2Fintroducing-descriptors-and-properties%2F&amp;style=normal" height="61" width="50" /><br />
			</a>
		</div>
<p>Note: This article was first published the <a href="http://www.pythonmagazine.com/c/issue/view/69">May 2008</a> issue of <a href="http://www.pythonmagazine.com/">Python Magazine</a></p>
<p><strong>Introducing Descriptors and Properties</strong></p>
<p><strong>Mark Mruss</strong></p>
<p>New-style classes were introduced to Python with the release of Python 2.2. And with these new-style classes came descriptors and properties. This article will introduce the descriptor protocol, descriptors, and properties.</p>
<h2>Introduction</h2>
<p>New-style classes were introduced to Python with the release of Python 2.2.  A new-style class is any class that is derived from the <code>object</code> base class. New-style classes give Python programmers many new (and initially confusing) features. One such feature is the descriptor protocol, and more specifically descriptors themselves.</p>
<p>Descriptors give Python programmers the ability to easily and efficiently create &#8220;managed attributes&#8221;. Managed attributes can be thought of as attributes that are not accessed directly. Instead their access is &#8220;managed&#8221; by something else, generally a class or a function.</p>
<p>If you haven&#8217;t come across this before you are probably wondering why one would want to manage attribute access? One reason might be that you don&#8217;t want people to be able to delete the attribute. Another reason may be that you need to ensure that your attribute data is always valid. Or perhaps attribute <code>x</code> is based on attribute <code>y</code>, so every time the value of <code>y</code> changes you want to update the value of <code>x</code>.  From these few examples you can see the many possible cases where you might want to control access to certain attributes.</p>
<p>For those of you familiar with other programming languages, this type of access is often referred to as &#8220;getters and setters&#8221;.  In many language, implementing &#8220;getters and setters&#8221; means using private variables and public functions that get and set the variable&#8217;s value. Since Python doesn&#8217;t (really) have private variables, the descriptor protocol is basically a built-in and “Python-ic” way to way to achieve something similar.</p>
<p>This article will introduce you to the descriptor protocol, descriptors, and properties. It will focus on demonstrating how to use them to create managed attributes. Since the descriptor protocol requires new-style classes, all of the examples in this article require Python 2.2 or newer.</p>
<p><span id="more-186"></span></p>
<h2>A few definitions</h2>
<p>Before moving forward, it is important to understand a few related terms. These terms will introduce some basic concepts and help you follow along with the remainder of the article.</p>
<p><strong>descriptor protocol</strong> &#8211; The following three methods make up the descriptor protocol: <code>__get__</code>, <code>__set__</code>, and <code>__delete__</code>.</p>
<p><strong>descriptor</strong> &#8211; An &#8220;object attribute with <code>binding behavior</code>, one whose attribute access has been overridden by methods in the descriptor protocol.&#8221; <a href="http://docs.python.org/ref/descriptor-invocation.html">[1]</a> In other words an &#8220;attributes whose usage resembles attribute access, but whose implementation uses method calls.&#8221;<a href="http://www.python.org/download/releases/2.2/descrintro/#property">[2]</a></p>
<p><strong>data descriptor</strong> &#8211; A descriptor with the <code>__get__</code> and <code>__set__</code> methods of the descriptor protocol defined.</p>
<p><strong>non-data descriptor</strong> &#8211; A descriptor with only the <code>__get__</code>  method of the descriptor protocol defined. &#8220;Python methods (including staticmethod() and classmethod()) are implemented as non-data descriptors.&#8221; <a href="http://docs.python.org/ref/descriptor-invocation.html">[3]</a></p>
<p><strong>property</strong> &#8211; A built-in type that implements the descriptor protocol and allows you to easily create data descriptors.</p>
<p>Don&#8217;t worry if you don&#8217;t fully understand these definitions, the remainder of this article will hopefully clarify any confusion you have.</p>
<h2>The Descriptor Protocol</h2>
<p>Let&#8217;s take a closer look at the descriptor protocol and see how we can use it to create a descriptor.  As previously mentioned, the descriptor protocol is made up of three methods: <code>__get__</code>, <code>__set__</code>, and <code>__delete__</code>.  These methods have specific signatures and they are as follows, where <code>self</code> is the class that owns the methods:</p>
<div class="hl-surround" ><div class="hl-main"><pre><span class="hl-identifier">__get__</span><span class="hl-brackets">(</span><span class="hl-identifier">self</span><span class="hl-code">, </span><span class="hl-identifier">instance</span><span class="hl-code">, </span><span class="hl-identifier">owner</span><span class="hl-brackets">)
</span><span class="hl-identifier">__set__</span><span class="hl-brackets">(</span><span class="hl-identifier">self</span><span class="hl-code">, </span><span class="hl-identifier">instance</span><span class="hl-code">, </span><span class="hl-identifier">value</span><span class="hl-brackets">)
</span><span class="hl-identifier">__delete__</span><span class="hl-brackets">(</span><span class="hl-identifier">self</span><span class="hl-code">, </span><span class="hl-identifier">instance</span><span class="hl-brackets">)</span></pre></div></div>
<p>These three methods represent the three basic operations that you perform on attributes in general: querying the value of that attribute; assigning a value to it; and, (very rarely) deleting it. They work as follows:</p>
<ul>
<li>
The <code>__get__</code> method is called when the attributes value is being queried.  The <code>__get__</code> method should return the (computed) attribute value or raise an AttributeError exception.&#8221; <a href="http://docs.python.org/ref/descriptors.html">[4]</a> This is where access to the attribute&#8217;s value is managed.
</li>
<li>
The <code>__set__</code> method is used in the assignment operation. It is called when we want to set the attribute value. This is where you can control what values, or types of values are being assigned to your attribute.
</li>
<li>Finally, the <code>__delete__</code> method is called when we want to delete the attribute. Here you can (rarely) decide whether or not to delete the attribute.
</li>
</ul>
<p>There are also three different parameters passed to the three methods (excluding the standard <code>self</code> parameter for methods that belong to a class):</p>
<ul>
<li>
<code>owner</code> &#8211; This &#8220;is always the owner class.&#8221; <a href="http://docs.python.org/ref/descriptors.html">[5]</a> This means that it is the actual class, and not an instance of the class. So if the descriptor is in a class called <code>MyClass</code>, <code>owner</code> will be that class.
</li>
<li>
<code>instance</code> &#8211; An instance of class type <code>owner</code>. It is &#8220;the instance that the attribute was accessed through&#8221; <a href="http://docs.python.org/ref/descriptors.html">[6]</a>, or <code>None</code> if the attribute is being accessed through the class (<code>owner</code>) instead of an instance.
</li>
<li>
<code>value</code>- The value that the attribute is being set to.
</li>
</ul>
<p>This difference between <code>owner</code> and <code>instance</code> might be a bit confusing, so let&#8217;s look at a quick example. Let’s say we have a descriptor <code>my_descriptor</code> in the class <code>MyClass</code>, if we were to run the following code:</p>
<div class="hl-surround" ><div class="hl-main"><pre><span class="hl-identifier">my_class_instance</span><span class="hl-default"> = </span><span class="hl-identifier">MyClass</span><span class="hl-brackets">()
</span><span class="hl-reserved">print </span><span class="hl-identifier">my_class_instance</span><span class="hl-default">.</span><span class="hl-identifier">my_descriptor</span></pre></div></div>
<p>The second line queries the descriptors value and results in the <code>__get__</code> method being called with the <code>instance</code> parameter being <code>my_class_instance</code>. The <code>owner</code> parameter will be the <code>MyClass</code> class.</p>
<p><strong>Note:</strong> Notice that we treat the descriptor <code>my_descriptor</code> as though it is a normal attribute. We don&#8217;t call <code>print my_class_instance.my_descriptor.__get__(my_class, MyClass)</code>. This is what was meant by: &#8220;attributes whose usage resembles attribute access, but whose implementation uses method calls.&#8221;<a href="http://www.python.org/download/releases/2.2/descrintro/#property">[7]</a></p>
<p>If the following code were run:</p>
<div class="hl-surround" style="height:28px;"><div class="hl-main"><pre><span class="hl-reserved">print </span><span class="hl-identifier">MyClass</span><span class="hl-default">.</span><span class="hl-identifier">my_descriptor</span></pre></div></div>
<p>The <code>__get__</code> method will again be called. This time the <code>instance</code> parameter will be <code>None</code> and the <code>owner</code> parameter will be the <code>MyClass</code> class.</p>
<p><strong>Note:</strong> Only the <code>__get__</code> method has the <code>owner</code> parameter. This means that it is the only function in the descriptor protocol that can be accessed through the class. Setting and deleting the descriptor through the class actually changes <strong>what</strong> the variable is. For example, if we tried to assign the numeric value 2 to a descriptor variable using the class, we would not access the descriptors <code>__set__</code> method. Instead we would change the type of the variable from a descriptor to an integer with the value of 2.</p>
<h2>A Simple Descriptor Example</h2>
<p>A simple &#8220;transparent&#8221; descriptor example can be found in Listing 1. The first thing to notice in the code is that both the <code>SimpleDescriptor</code> and <code>MyClass</code> classes are &#8220;new-style&#8221; classes because they are derived from <code>object</code>. This is important because, as mentioned above, descriptors only work with &#8220;new-style&#8221; classes. The second point to notice is that the descriptor has class scope as opposed to instance scope. There are also two extra print statements included in the code. They are there to let us follow the execution a little more easily.</p>
<p><strong>Listing 1</strong></p>
<div class="hl-surround" ><div class="hl-main"><pre><span class="hl-reserved">class </span><span class="hl-identifier">SimpleDescriptor</span><span class="hl-brackets">(</span><span class="hl-identifier">object</span><span class="hl-brackets">)</span><span class="hl-default">:

    </span><span class="hl-reserved">def </span><span class="hl-identifier">__get__</span><span class="hl-brackets">(</span><span class="hl-identifier">self</span><span class="hl-code">, </span><span class="hl-identifier">instance</span><span class="hl-code">, </span><span class="hl-identifier">owner</span><span class="hl-brackets">)</span><span class="hl-default">:
        </span><span class="hl-comment"># Check if the value has been set
        </span><span class="hl-identifier">if </span><span class="hl-brackets">(</span><span class="hl-reserved">not </span><span class="hl-builtin">hasattr</span><span class="hl-brackets">(</span><span class="hl-identifier">self</span><span class="hl-code">, </span><span class="hl-quotes">&quot;</span><span class="hl-string">_value</span><span class="hl-quotes">&quot;</span><span class="hl-brackets">))</span><span class="hl-default">:
            </span><span class="hl-reserved">raise AttributeError
        print </span><span class="hl-quotes">&quot;</span><span class="hl-string">Getting value: %s</span><span class="hl-quotes">&quot;</span><span class="hl-default"> % </span><span class="hl-identifier">self</span><span class="hl-default">.</span><span class="hl-identifier">_value
        </span><span class="hl-reserved">return </span><span class="hl-identifier">self</span><span class="hl-default">.</span><span class="hl-identifier">_value

    </span><span class="hl-reserved">def </span><span class="hl-identifier">__set__</span><span class="hl-brackets">(</span><span class="hl-identifier">self</span><span class="hl-code">, </span><span class="hl-identifier">instance</span><span class="hl-code">, </span><span class="hl-identifier">value</span><span class="hl-brackets">)</span><span class="hl-default">:
        </span><span class="hl-reserved">print </span><span class="hl-quotes">&quot;</span><span class="hl-string">Setting to %s</span><span class="hl-quotes">&quot;</span><span class="hl-default"> % </span><span class="hl-identifier">value
        self</span><span class="hl-default">.</span><span class="hl-identifier">_value</span><span class="hl-default"> = </span><span class="hl-identifier">value

    </span><span class="hl-reserved">def </span><span class="hl-identifier">__delete__</span><span class="hl-brackets">(</span><span class="hl-identifier">self</span><span class="hl-code">, </span><span class="hl-identifier">instance</span><span class="hl-brackets">)</span><span class="hl-default">:
        </span><span class="hl-identifier">del</span><span class="hl-brackets">(</span><span class="hl-identifier">self</span><span class="hl-code">.</span><span class="hl-identifier">_value</span><span class="hl-brackets">)

</span><span class="hl-reserved">class </span><span class="hl-identifier">MyClass</span><span class="hl-brackets">(</span><span class="hl-identifier">object</span><span class="hl-brackets">)</span><span class="hl-default">:
    </span><span class="hl-identifier">my_value</span><span class="hl-default"> = </span><span class="hl-identifier">SimpleDescriptor</span><span class="hl-brackets">()</span></pre></div></div>
<p>Using Listing 1 to execute the following code:</p>
<div class="hl-surround" ><div class="hl-main"><pre><span class="hl-identifier">my_instance</span><span class="hl-default"> = </span><span class="hl-identifier">MyClass</span><span class="hl-brackets">()
</span><span class="hl-identifier">my_instance</span><span class="hl-default">.</span><span class="hl-identifier">my_value</span><span class="hl-default"> = </span><span class="hl-number">416
</span><span class="hl-reserved">print </span><span class="hl-identifier">my_instance</span><span class="hl-default">.</span><span class="hl-identifier">my_value</span></pre></div></div>
<p>The output would be the following:</p>
<div class="hl-surround" ><div class="hl-main"><pre><span class="hl-identifier">Setting to </span><span class="hl-number">416
</span><span class="hl-identifier">Getting value</span><span class="hl-default">: </span><span class="hl-number">416
416</span></pre></div></div>
<p>As you can see the second line (<code>my_instance.data_descriptor = 416</code>) calls the <code>__set__</code> method and sets the _value attribute. When we call <code>print my_instance.data_descriptor</code> the <code>__get__</code>, method is called and the <code>_value</code> attribute is returned.</p>
<h2>The Problem with the Simple Example</h2>
<p>The previous example may look like a perfectly good descriptor, but there is something wrong with it. Take a look at what happens when we runs this new code:</p>
<div class="hl-surround" ><div class="hl-main"><pre><span class="hl-identifier">my_instance</span><span class="hl-default"> = </span><span class="hl-identifier">MyClass</span><span class="hl-brackets">() </span><span class="hl-comment">#Create the first instance
</span><span class="hl-identifier">my_instance</span><span class="hl-default">.</span><span class="hl-identifier">my_value</span><span class="hl-default"> = </span><span class="hl-number">416 </span><span class="hl-comment">#Set its' value
</span><span class="hl-identifier">my_second_instance</span><span class="hl-default"> = </span><span class="hl-identifier">MyClass</span><span class="hl-brackets">() </span><span class="hl-comment">#Create the second instance
</span><span class="hl-identifier">my_second_instance</span><span class="hl-default">.</span><span class="hl-identifier">my_value</span><span class="hl-default"> = </span><span class="hl-number">204 </span><span class="hl-comment">#Set its' value
</span><span class="hl-reserved">print </span><span class="hl-identifier">my_instance</span><span class="hl-default">.</span><span class="hl-identifier">my_value </span><span class="hl-comment">#What was the fist instance's value?</span></pre></div></div>
<p>We get the following output:</p>
<div class="hl-surround" ><div class="hl-main"><pre><span class="hl-identifier">Setting to </span><span class="hl-number">416
</span><span class="hl-identifier">Setting to </span><span class="hl-number">204
</span><span class="hl-identifier">Getting value</span><span class="hl-default">: </span><span class="hl-number">204
204</span></pre></div></div>
<p>Notice that when we set the second instance&#8217;s <code>my_value</code> descriptor to be 204, we are also setting the first instances. This is because <code>my_value</code> has class scope, so both instances (and the class itself) share the same instance of the <code>SimpleDescriptor</code> class. Since <code>SimpleDescriptor</code> only stores one value, they all actually share the same value. We will get the same results if we check what the classes value of <code>my_value</code> is:</p>
<div class="hl-surround" ><div class="hl-main"><pre><span class="hl-identifier">my_instance</span><span class="hl-default"> = </span><span class="hl-identifier">MyClass</span><span class="hl-brackets">() </span><span class="hl-comment">#Create the first instance
</span><span class="hl-identifier">my_instance</span><span class="hl-default">.</span><span class="hl-identifier">my_value</span><span class="hl-default"> = </span><span class="hl-number">416 </span><span class="hl-comment">#Set its' value
</span><span class="hl-identifier">my_second_instance</span><span class="hl-default"> = </span><span class="hl-identifier">MyClass</span><span class="hl-brackets">() </span><span class="hl-comment">#Create the second instance
</span><span class="hl-identifier">my_second_instance</span><span class="hl-default">.</span><span class="hl-identifier">my_value</span><span class="hl-default"> = </span><span class="hl-number">204 </span><span class="hl-comment">#Set its' value
</span><span class="hl-reserved">print </span><span class="hl-identifier">MyClass</span><span class="hl-default">.</span><span class="hl-identifier">my_value </span><span class="hl-comment">#What's the classes value?</span></pre></div></div>
<p>We get the following results:</p>
<div class="hl-surround" ><div class="hl-main"><pre><span class="hl-identifier">Setting to </span><span class="hl-number">416
</span><span class="hl-identifier">Setting to </span><span class="hl-number">204
</span><span class="hl-identifier">Getting value</span><span class="hl-default">: </span><span class="hl-number">204
204</span></pre></div></div>
<p>In the last line of the code (<code>print MyClass.my_value #What's the classes value?</code>) we simply use the class (ignoring both instances) in order to get the value of <code>my_data</code>. This will be an instance where the <code>__get__</code> function will be called with the <code>instance</code> parameter set to <code>None</code>.</p>
<p><strong>Note:</strong> This is not a problem if you want to share the value across all instances.</p>
<h2>The Solution to the Problem</h2>
<p>In order to get around this issue, you have to remember that if you want values unique to each instance your descriptors must store values that are unique to each instance. This can be in the instance itself, in dictionary in the descriptor, or perhaps in a text file. Just make sure that the value is unique to each instance. Though it seems like a simple solution, in practice a suitable solution for all cases is difficult to implement. As a result you should probably pick a specific implementation for your specific situations.</p>
<p>Using each instance as a key, one can store the value in a dictionary in the descriptor itself. The problem with this solution should be obvious to programmers familiar with Python dictionaries: only immutable types can be used as keys. This is fine if you know what object you are working with, but what about in the future when you want to add a descriptor to your sub-classed list?</p>
<p>Another solution is to store the value in the instance itself. You can do this by easily adding the value to the instance&#8217;s <code>__dict__</code>. The limitation is that the descriptor need to be given a suitable key so that there is no collision with anything already in the instance&#8217;s <code>__dict__</code>.</p>
<p>Listing 2 shows a solution to the problem from the previous section where the value is stored in the instance&#8217;s <code>__dict__</code>. Values are indexed using a key name provided during the creation of the descriptor.  Aside from where we store the value, there is little difference between Listing 1 and Listing 2.  Notice that the value name is a converted into a string. This is done to ensure that it can be used as a key.</p>
<p><strong>Listing 2</strong></p>
<div class="hl-surround" style="height:280px;"><div class="hl-main"><pre><span class="hl-reserved">class </span><span class="hl-identifier">FixedDescriptor</span><span class="hl-brackets">(</span><span class="hl-identifier">object</span><span class="hl-brackets">)</span><span class="hl-default">:

</span><span class="hl-reserved">def </span><span class="hl-identifier">__init__</span><span class="hl-brackets">(</span><span class="hl-identifier">self</span><span class="hl-code">, </span><span class="hl-identifier">value_name</span><span class="hl-brackets">)</span><span class="hl-default">:
    </span><span class="hl-identifier">self</span><span class="hl-default">.</span><span class="hl-identifier">value_name</span><span class="hl-default"> = </span><span class="hl-builtin">str</span><span class="hl-brackets">(</span><span class="hl-identifier">value_name</span><span class="hl-brackets">)

</span><span class="hl-reserved">def </span><span class="hl-identifier">__get__</span><span class="hl-brackets">(</span><span class="hl-identifier">self</span><span class="hl-code">, </span><span class="hl-identifier">instance</span><span class="hl-code">, </span><span class="hl-identifier">owner</span><span class="hl-brackets">)</span><span class="hl-default">:
    </span><span class="hl-identifier">if </span><span class="hl-brackets">(</span><span class="hl-identifier">instance </span><span class="hl-reserved">is None</span><span class="hl-brackets">)</span><span class="hl-default">:
        </span><span class="hl-reserved">raise AttributeError
    </span><span class="hl-identifier">elif </span><span class="hl-brackets">(</span><span class="hl-reserved">not </span><span class="hl-identifier">instance</span><span class="hl-code">.</span><span class="hl-identifier">__dict__</span><span class="hl-code">.</span><span class="hl-identifier">has_key</span><span class="hl-brackets">(</span><span class="hl-identifier">self</span><span class="hl-code">.</span><span class="hl-identifier">value_name</span><span class="hl-brackets">))</span><span class="hl-default">:
        </span><span class="hl-reserved">raise AttributeError
    return </span><span class="hl-identifier">instance</span><span class="hl-default">.</span><span class="hl-identifier">__dict__</span><span class="hl-brackets">[</span><span class="hl-identifier">self</span><span class="hl-code">.</span><span class="hl-identifier">value_name</span><span class="hl-brackets">]

    </span><span class="hl-reserved">def </span><span class="hl-identifier">__set__</span><span class="hl-brackets">(</span><span class="hl-identifier">self</span><span class="hl-code">, </span><span class="hl-identifier">instance</span><span class="hl-code">, </span><span class="hl-identifier">value</span><span class="hl-brackets">)</span><span class="hl-default">:
        </span><span class="hl-reserved">print </span><span class="hl-quotes">&quot;</span><span class="hl-string">Setting to %s</span><span class="hl-quotes">&quot;</span><span class="hl-default"> % </span><span class="hl-identifier">value
        instance</span><span class="hl-default">.</span><span class="hl-identifier">__dict__</span><span class="hl-brackets">[</span><span class="hl-identifier">self</span><span class="hl-code">.</span><span class="hl-identifier">value_name</span><span class="hl-brackets">]</span><span class="hl-default"> = </span><span class="hl-identifier">value

    </span><span class="hl-reserved">def </span><span class="hl-identifier">__delete__</span><span class="hl-brackets">(</span><span class="hl-identifier">self</span><span class="hl-code">, </span><span class="hl-identifier">instance</span><span class="hl-brackets">)</span><span class="hl-default">:
        </span><span class="hl-identifier">if </span><span class="hl-brackets">(</span><span class="hl-identifier">instance</span><span class="hl-code">.</span><span class="hl-identifier">__dict__</span><span class="hl-code">.</span><span class="hl-identifier">has_key</span><span class="hl-brackets">(</span><span class="hl-identifier">self</span><span class="hl-code">.</span><span class="hl-identifier">value_name</span><span class="hl-brackets">))</span><span class="hl-default">:
            </span><span class="hl-identifier">del</span><span class="hl-brackets">(</span><span class="hl-identifier">instance</span><span class="hl-code">.</span><span class="hl-identifier">__dict__</span><span class="hl-brackets">[</span><span class="hl-identifier">self</span><span class="hl-code">.</span><span class="hl-identifier">value_name</span><span class="hl-brackets">])


</span><span class="hl-reserved">class </span><span class="hl-identifier">MyClass</span><span class="hl-brackets">(</span><span class="hl-identifier">object</span><span class="hl-brackets">)</span><span class="hl-default">:
    </span><span class="hl-identifier">my_value</span><span class="hl-default"> = </span><span class="hl-identifier">FixedDescriptor</span><span class="hl-brackets">(</span><span class="hl-quotes">&quot;</span><span class="hl-string">__value</span><span class="hl-quotes">&quot;</span><span class="hl-brackets">)</span></pre></div></div>
<p>The major usage difference between Listing 1 and Listing 2 is the fact that the <code>__get__</code> method no longer works at class level; it only works at instance level. This should be obvious since this solution stores the value in the instance.  If there is no instance, we have nowhere to store the value!  If you attempt to access the descriptor at class level (the first if statement) an attribute error will be raised:</p>
<div class="hl-surround" ><div class="hl-main"><pre><span class="hl-reserved">def </span><span class="hl-identifier">__get__</span><span class="hl-brackets">(</span><span class="hl-identifier">self</span><span class="hl-code">, </span><span class="hl-identifier">instance</span><span class="hl-code">, </span><span class="hl-identifier">owner</span><span class="hl-brackets">)</span><span class="hl-default">:
    </span><span class="hl-identifier">if </span><span class="hl-brackets">(</span><span class="hl-identifier">instance </span><span class="hl-reserved">is None</span><span class="hl-brackets">)</span><span class="hl-default">:
        </span><span class="hl-reserved">raise AttributeError
    </span><span class="hl-identifier">elif </span><span class="hl-brackets">(</span><span class="hl-reserved">not </span><span class="hl-identifier">instance</span><span class="hl-code">.</span><span class="hl-identifier">__dict__</span><span class="hl-code">.</span><span class="hl-identifier">has_key</span><span class="hl-brackets">(</span><span class="hl-identifier">self</span><span class="hl-code">.</span><span class="hl-identifier">value_name</span><span class="hl-brackets">))</span><span class="hl-default">:
        </span><span class="hl-reserved">raise AttributeError
    return </span><span class="hl-identifier">instance</span><span class="hl-default">.</span><span class="hl-identifier">__dict__</span><span class="hl-brackets">[</span><span class="hl-identifier">self</span><span class="hl-code">.</span><span class="hl-identifier">value_name</span><span class="hl-brackets">]</span></pre></div></div>
<h2>Easy Data Descriptors with Properties</h2>
<p>The descriptor provided in Listing 2 will work for many situations but for my money the easiest way to implement data descriptors is to use the <code>property</code> type. I would recommend using it unless you need the same descriptor across many different classes or attributes (i.e. for type validation). Properties can be thought of as a simple and easy way to create data descriptors. The <code>property</code> type implements the descriptor protocol and gets around the problem of where to store the descriptor value in an easy way: it lets the class that created the descriptor deal with it.</p>
<p>The full signature of the <code>property</code> function is as follows:</p>
<div class="hl-surround" style="height:28px;"><div class="hl-main"><pre><span class="hl-builtin">property</span><span class="hl-brackets">(</span><span class="hl-identifier">fget</span><span class="hl-code">=</span><span class="hl-reserved">None</span><span class="hl-code">, </span><span class="hl-identifier">fset</span><span class="hl-code">=</span><span class="hl-reserved">None</span><span class="hl-code">, </span><span class="hl-identifier">fdel</span><span class="hl-code">=</span><span class="hl-reserved">None</span><span class="hl-code">, </span><span class="hl-identifier">doc</span><span class="hl-code">=</span><span class="hl-reserved">None</span><span class="hl-brackets">)</span></pre></div></div>
<p>Where <code>fget</code>, <code>fset</code>, <code>fdel</code> are methods that will be called when the <code>__get__</code>, <code>__set__</code>, and <code>__del__</code> members of the descriptor protocol are called. The <code>doc</code> parameter is a string that will be used as the docstring for the descriptor.  If the <code>doc</code> parameter is not specified, the docstring of the <code>fget</code> method is used.</p>
<p>The signature of the <code>fget</code>, <code>fset</code>, <code>fdel</code> functions are as follows:</p>
<div class="hl-surround" ><div class="hl-main"><pre><span class="hl-identifier">fget</span><span class="hl-brackets">(</span><span class="hl-identifier">instance</span><span class="hl-brackets">)
</span><span class="hl-identifier">fset</span><span class="hl-brackets">(</span><span class="hl-identifier">instance</span><span class="hl-code">, </span><span class="hl-identifier">value</span><span class="hl-brackets">)
</span><span class="hl-identifier">fdel</span><span class="hl-brackets">(</span><span class="hl-identifier">instance</span><span class="hl-brackets">)</span></pre></div></div>
<p>In the three signatures, <code>instance</code> is a reference to the object that owns the property attribute. This is the same instance that gets passed to the descriptor protocol.  Since <code>instance</code> is the first parameter of each method, these are, for all intents and purposes, member methods of a class. The <code>value</code> parameter is the same as the <code>value</code> parameter that is passed to the <code>__set__</code> method. It is what we are setting the attribute to.</p>
<p>The basic way to implement properties can be seen in Listing 3. As you can see, what we do for a property is very similar to what we did for our initial descriptor in Listing 1. We set up the three functions necessary for the descriptor protocol, and then use them to create our property attribute.  Creating the property is very simple:</p>
<p><strong>Listing 3</strong></p>
<div class="hl-surround" style="height:280px;"><div class="hl-main"><pre><span class="hl-reserved">class </span><span class="hl-identifier">MyClass</span><span class="hl-brackets">(</span><span class="hl-identifier">object</span><span class="hl-brackets">)</span><span class="hl-default">:
    </span><span class="hl-comment">#Create the fget, fset, and fdel methods
    </span><span class="hl-reserved">def </span><span class="hl-identifier">__get_value</span><span class="hl-brackets">(</span><span class="hl-identifier">self</span><span class="hl-brackets">)</span><span class="hl-default">:
        </span><span class="hl-reserved">print </span><span class="hl-quotes">&quot;</span><span class="hl-string">Getting value: %s</span><span class="hl-quotes">&quot;</span><span class="hl-default"> % </span><span class="hl-identifier">self</span><span class="hl-default">.</span><span class="hl-identifier">__value
        </span><span class="hl-reserved">return </span><span class="hl-identifier">self</span><span class="hl-default">.</span><span class="hl-identifier">__value

    </span><span class="hl-reserved">def </span><span class="hl-identifier">__set_value</span><span class="hl-brackets">(</span><span class="hl-identifier">self</span><span class="hl-code">, </span><span class="hl-identifier">value</span><span class="hl-brackets">)</span><span class="hl-default">:
        </span><span class="hl-reserved">print </span><span class="hl-quotes">&quot;</span><span class="hl-string">Setting to %s</span><span class="hl-quotes">&quot;</span><span class="hl-default"> % </span><span class="hl-identifier">value
        self</span><span class="hl-default">.</span><span class="hl-identifier">__value</span><span class="hl-default"> = </span><span class="hl-identifier">value

    </span><span class="hl-reserved">def </span><span class="hl-identifier">__del_value</span><span class="hl-brackets">(</span><span class="hl-identifier">self</span><span class="hl-brackets">)</span><span class="hl-default">:
        </span><span class="hl-identifier">del</span><span class="hl-brackets">(</span><span class="hl-identifier">self</span><span class="hl-code">.</span><span class="hl-identifier">__value</span><span class="hl-brackets">)

    </span><span class="hl-comment">#Create the property
    </span><span class="hl-identifier">my_value</span><span class="hl-default"> = </span><span class="hl-builtin">property</span><span class="hl-brackets">(</span><span class="hl-identifier">__get_value</span><span class="hl-code">
            , </span><span class="hl-identifier">__set_value</span><span class="hl-code">
            , </span><span class="hl-identifier">__del_value</span><span class="hl-code">
            , </span><span class="hl-quotes">&quot;</span><span class="hl-string">This is my property</span><span class="hl-quotes">&quot;</span><span class="hl-brackets">)

    </span><span class="hl-reserved">def </span><span class="hl-identifier">__init__</span><span class="hl-brackets">(</span><span class="hl-identifier">self</span><span class="hl-code">, </span><span class="hl-identifier">value</span><span class="hl-code">=</span><span class="hl-number">0</span><span class="hl-brackets">)</span><span class="hl-default">:
        </span><span class="hl-identifier">self</span><span class="hl-default">.</span><span class="hl-identifier">my_value</span><span class="hl-default"> = </span><span class="hl-identifier">value</span></pre></div></div>
<div class="hl-surround" ><div class="hl-main"><pre><span class="hl-identifier">my_value</span><span class="hl-default"> = </span><span class="hl-builtin">property</span><span class="hl-brackets">(</span><span class="hl-identifier">__get_value</span><span class="hl-code">
        , </span><span class="hl-identifier">__set_value</span><span class="hl-code">
        , </span><span class="hl-identifier">__del_value</span><span class="hl-code">
        , </span><span class="hl-quotes">&quot;</span><span class="hl-string">This is my property</span><span class="hl-quotes">&quot;</span><span class="hl-brackets">)</span></pre></div></div>
<h2>Make Data Attributes Data-Descriptors</h2>
<p>A common reason to use descriptors is to create read-only attributes. This means allowing callers to get (or access) an attribute&#8217;s value, but not allowing them to set its&#8217; value. At first glance it seems as though one can accomplish this by using descriptors with only the <code>__get__</code> method defined, i.e. a &#8220;non-data descriptor&#8221;.</p>
<p>While this seems to create a read-only descriptor attribute, it actually does nothing of the sort. Instead of using the descriptor&#8217;s <code>__set__</code> function for the assignment operation (since no <code>__set__</code> function is defined), the default Python assignment operation is used. This means that instead of stopping the assignment operation, a new attribute will be created in the instance (remember that descriptors have class scope) having the same name as the descriptor attribute and taking precedence in future operations.</p>
<p>This may be a bit confusing so let&#8217;s look at the example in Listing 4. It&#8217;s very much like our previous descriptor examples except it does not specify the <code>__set__</code> and <code>__del__</code> functions. Let’s look at what happens when we try to use this as though it were a read-only attribute:</p>
<p><strong>Listing 4</strong></p>
<div class="hl-surround" ><div class="hl-main"><pre><span class="hl-reserved">class </span><span class="hl-identifier">WonkyDescriptor</span><span class="hl-brackets">(</span><span class="hl-identifier">object</span><span class="hl-brackets">)</span><span class="hl-default">:
    </span><span class="hl-quotes">&quot;&quot;&quot;</span><span class="hl-string">This Descriptor isn't read only</span><span class="hl-quotes">&quot;&quot;&quot;
    </span><span class="hl-reserved">def </span><span class="hl-identifier">__init__</span><span class="hl-brackets">(</span><span class="hl-identifier">self</span><span class="hl-code">, </span><span class="hl-identifier">value_name</span><span class="hl-brackets">)</span><span class="hl-default">:
        </span><span class="hl-identifier">self</span><span class="hl-default">.</span><span class="hl-identifier">value_name</span><span class="hl-default"> = </span><span class="hl-builtin">str</span><span class="hl-brackets">(</span><span class="hl-identifier">value_name</span><span class="hl-brackets">)

    </span><span class="hl-reserved">def </span><span class="hl-identifier">__get__</span><span class="hl-brackets">(</span><span class="hl-identifier">self</span><span class="hl-code">, </span><span class="hl-identifier">instance</span><span class="hl-code">, </span><span class="hl-identifier">owner</span><span class="hl-brackets">)</span><span class="hl-default">:
        </span><span class="hl-identifier">if </span><span class="hl-brackets">(</span><span class="hl-identifier">instance </span><span class="hl-reserved">is None</span><span class="hl-brackets">)</span><span class="hl-default">:
            </span><span class="hl-reserved">raise AttributeError
        </span><span class="hl-identifier">elif </span><span class="hl-brackets">(</span><span class="hl-reserved">not </span><span class="hl-identifier">instance</span><span class="hl-code">.</span><span class="hl-identifier">__dict__</span><span class="hl-code">.</span><span class="hl-identifier">has_key</span><span class="hl-brackets">(</span><span class="hl-identifier">self</span><span class="hl-code">.</span><span class="hl-identifier">value_name</span><span class="hl-brackets">))</span><span class="hl-default">:
            </span><span class="hl-reserved">raise AttributeError
        print </span><span class="hl-quotes">&quot;</span><span class="hl-string">Getting a value</span><span class="hl-quotes">&quot;
        </span><span class="hl-reserved">return </span><span class="hl-identifier">instance</span><span class="hl-default">.</span><span class="hl-identifier">__dict__</span><span class="hl-brackets">[</span><span class="hl-identifier">self</span><span class="hl-code">.</span><span class="hl-identifier">value_name</span><span class="hl-brackets">]

</span><span class="hl-reserved">class </span><span class="hl-identifier">MyClass</span><span class="hl-brackets">(</span><span class="hl-identifier">object</span><span class="hl-brackets">)</span><span class="hl-default">:

    </span><span class="hl-identifier">my_value</span><span class="hl-default"> = </span><span class="hl-identifier">WonkyDescriptor</span><span class="hl-brackets">(</span><span class="hl-quotes">&quot;</span><span class="hl-string">_value</span><span class="hl-quotes">&quot;</span><span class="hl-brackets">)

    </span><span class="hl-reserved">def </span><span class="hl-identifier">__init__</span><span class="hl-brackets">(</span><span class="hl-identifier">self</span><span class="hl-code">, </span><span class="hl-identifier">value</span><span class="hl-brackets">)</span><span class="hl-default">:
        </span><span class="hl-comment">#initial value
        </span><span class="hl-identifier">self</span><span class="hl-default">.</span><span class="hl-identifier">_value</span><span class="hl-default"> = </span><span class="hl-identifier">value</span></pre></div></div>
<div class="hl-surround" ><div class="hl-main"><pre><span class="hl-identifier">my_instance</span><span class="hl-default"> = </span><span class="hl-identifier">MyClass</span><span class="hl-brackets">(</span><span class="hl-number">23</span><span class="hl-brackets">) </span><span class="hl-comment">#Create the first instance
</span><span class="hl-reserved">print </span><span class="hl-identifier">my_instance</span><span class="hl-default">.</span><span class="hl-identifier">my_value
my_instance</span><span class="hl-default">.</span><span class="hl-identifier">my_value</span><span class="hl-default"> = </span><span class="hl-quotes">&quot;</span><span class="hl-string">Don't set me!</span><span class="hl-quotes">&quot;
</span><span class="hl-reserved">print </span><span class="hl-identifier">my_instance</span><span class="hl-default">.</span><span class="hl-identifier">my_value</span></pre></div></div>
<p>When we run this, we get the following output:</p>
<div class="hl-surround" ><div class="hl-main"><pre><span class="hl-identifier">Getting a value
</span><span class="hl-number">23
</span><span class="hl-identifier">Don</span><span class="hl-quotes">'</span><span class="hl-string">t set me!</span></pre></div></div>
<p>As you can see we did not succeed in creating a read-only attribute, instead something else happened. The &#8220;Getting a value&#8221; string is printed out when we print out <code>my_value</code> for the first time. This means that we are accessing the value through the descriptor. We then set the value of the descriptor attribute and print out that new value. Since &#8220;Getting a value&#8221; isn&#8217;t printed out a second time, we know that the descriptor&#8217;s <code>__get__</code> method is not accessed when the second print statement is called.</p>
<p>Let&#8217;s take a closer look at what is happening using the following code, which prints out the instance&#8217;s <code>__dict__</code>:</p>
<div class="hl-surround" ><div class="hl-main"><pre><span class="hl-identifier">my_instance</span><span class="hl-default"> = </span><span class="hl-identifier">MyClass</span><span class="hl-brackets">(</span><span class="hl-number">23</span><span class="hl-brackets">) </span><span class="hl-comment">#Create the first instance
</span><span class="hl-reserved">print </span><span class="hl-identifier">my_instance</span><span class="hl-default">.</span><span class="hl-identifier">__dict__
my_instance</span><span class="hl-default">.</span><span class="hl-identifier">my_value</span><span class="hl-default"> = </span><span class="hl-quotes">&quot;</span><span class="hl-string">Don't set me!</span><span class="hl-quotes">&quot;
</span><span class="hl-reserved">print </span><span class="hl-identifier">my_instance</span><span class="hl-default">.</span><span class="hl-identifier">__dict__</span></pre></div></div>
<p>This results in the following, which explains what is happening:</p>
<div class="hl-surround" ><div class="hl-main"><pre><span class="hl-default">{</span><span class="hl-quotes">'</span><span class="hl-string">_value</span><span class="hl-quotes">'</span><span class="hl-default">: </span><span class="hl-number">23</span><span class="hl-default">}
{</span><span class="hl-quotes">'</span><span class="hl-string">_value</span><span class="hl-quotes">'</span><span class="hl-default">: </span><span class="hl-number">23</span><span class="hl-default">, </span><span class="hl-quotes">'</span><span class="hl-string">my_value</span><span class="hl-quotes">'</span><span class="hl-default">: </span><span class="hl-quotes">&quot;</span><span class="hl-string">Don't set me!</span><span class="hl-quotes">&quot;</span><span class="hl-default">}</span></pre></div></div>
<p>When we first access the <code>__dict__</code> we see our value indexed by the <code>_value</code> key that we told the descriptor to use. Now look at the second <code>__dict__</code>. The old value is still there, but so is a new value <code>my_value</code>. When we assigned &#8220;Don&#8217;t set me!&#8221; to <code>my_value</code>, we didn&#8217;t overwrite the descriptor attribute at class scope, we created a new instance attribute! And it is not exactly a read-only attribute.</p>
<p>In order to create a read-only attribute, you need to create a <code>data descriptor</code> where the <code>__set__</code> method raises an <code>AttributeError</code> exception. An easy way to do this is to create a <code>property</code> and only set the <code>fget</code> function. Instead of using the descriptor in Listing 4, we can construct a read-only attribute as follows:</p>
<div class="hl-surround" ><div class="hl-main"><pre><span class="hl-reserved">def </span><span class="hl-identifier">__get_value</span><span class="hl-brackets">(</span><span class="hl-identifier">self</span><span class="hl-brackets">)</span><span class="hl-default">:
    </span><span class="hl-reserved">return </span><span class="hl-identifier">self</span><span class="hl-default">.</span><span class="hl-identifier">_value
my_value</span><span class="hl-default"> = </span><span class="hl-builtin">property</span><span class="hl-brackets">(</span><span class="hl-identifier">__get_value</span><span class="hl-brackets">)</span></pre></div></div>
<h2>Conclusion</h2>
<p>I hope that after reading this article you can see how powerful descriptors (especially data-descriptors) can be. Once you get the hang of them, they are a great way to implement &#8220;getters and setters&#8221; and read-only attributes. Data-Descriptors are also very useful for performing validation during the assignment operation, i.e. ensuring that a value remains a specific type, or in a specific form.</p>
<p>The more you play with descriptors and use them in your code, the more you&#8217;ll see how sophisticated and useful they can be. That being said, it&#8217;s important to remember that unless you have a good reason to use descriptors you probably don&#8217;t need them. There&#8217;s no need to sacrifice the readability of your code or the dynamism of Python just for the sake of using descriptors. But when you have a real reason for managed attributes, you&#8217;ll find that descriptors are more than up to the task.</p>
<p>[1] <a href="http://docs.python.org/ref/descriptor-invocation.html">http://docs.python.org/ref/descriptor-invocation.html</a><br />
[2] <a href="http://www.python.org/download/releases/2.2/descrintro/#property">http://www.python.org/download/releases/2.2/descrintro/#property</a><br />
[3] <a href="http://docs.python.org/ref/descriptor-invocation.html">http://docs.python.org/ref/descriptor-invocation.html</a><br />
[4] <a href="http://docs.python.org/ref/descriptors.html">http://docs.python.org/ref/descriptors.html</a><br />
[5] <a href="http://docs.python.org/ref/descriptors.html">http://docs.python.org/ref/descriptors.html</a><br />
[6] <a href="http://docs.python.org/ref/descriptors.html">http://docs.python.org/ref/descriptors.html</a><br />
[7] <a href="http://www.python.org/download/releases/2.2/descrintro/#property">http://www.python.org/download/releases/2.2/descrintro/#property</a></p>
<div style="float:right;margin:0px 0px 0px 0px;"><a href="http://www.google.com/reader/link?url=http://www.learningpython.com/2010/04/25/introducing-descriptors-and-properties/&title=Introducing Descriptors and Properties&srcTitle=learning python&srcURL=http://www.learningpython.com"target="_blank" rel=""><img border="0" src="http://www.learningpython.com/wp-content/plugins/wp-google-buzz/icon/12.png" style="opacity:1;filter:alpha(opacity=100)" onmouseover="this.style.opacity=0.8;this.filters.alpha.opacity=70" onmouseout="this.style.opacity=1;this.filters.alpha.opacity=100"/> </a></div>]]></content:encoded>
			<wfw:commentRss>http://www.learningpython.com/2010/04/25/introducing-descriptors-and-properties/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Forums Forums Forums</title>
		<link>http://www.learningpython.com/2010/04/08/forums-forums-forums-2/</link>
		<comments>http://www.learningpython.com/2010/04/08/forums-forums-forums-2/#comments</comments>
		<pubDate>Fri, 09 Apr 2010 03:05:33 +0000</pubDate>
		<dc:creator>selsine</dc:creator>
				<category><![CDATA[python]]></category>
		<category><![CDATA[forums]]></category>

		<guid isPermaLink="false">http://www.learningpython.com/?p=183</guid>
		<description><![CDATA[
			
				
			
		
I just wanted to re-point out the fact that there are some forums associated with this blog.  There&#8217;s not much happening there, and recently they have become a haven for spammers, but I&#8217;m trying to clean them up and if other Python programmers read this blog maybe the forums could actually become useful!
Either way [...]]]></description>
			<content:encoded><![CDATA[<div class="tweetmeme_button" style="float: right; margin-left: 10px;">
			<a href="http://api.tweetmeme.com/share?url=http%3A%2F%2Fwww.learningpython.com%2F2010%2F04%2F08%2Fforums-forums-forums-2%2F"><br />
				<img src="http://api.tweetmeme.com/imagebutton.gif?url=http%3A%2F%2Fwww.learningpython.com%2F2010%2F04%2F08%2Fforums-forums-forums-2%2F&amp;style=normal" height="61" width="50" /><br />
			</a>
		</div>
<p>I just wanted to re-point out the fact that there are some <a href="http://www.learningpython.com/forums">forums associated with this blog</a>.  There&#8217;s not much happening there, and recently they have become a haven for spammers, but I&#8217;m trying to clean them up and if other Python programmers read this blog maybe the forums could actually become useful!</p>
<p>Either way for those that didn&#8217;t know, there are <a href="http://www.learningpython.com/forums">learning python forums</a> available.</p>
<div style="float:right;margin:0px 0px 0px 0px;"><a href="http://www.google.com/reader/link?url=http://www.learningpython.com/2010/04/08/forums-forums-forums-2/&title=Forums Forums Forums&srcTitle=learning python&srcURL=http://www.learningpython.com"target="_blank" rel=""><img border="0" src="http://www.learningpython.com/wp-content/plugins/wp-google-buzz/icon/12.png" style="opacity:1;filter:alpha(opacity=100)" onmouseover="this.style.opacity=0.8;this.filters.alpha.opacity=70" onmouseout="this.style.opacity=1;this.filters.alpha.opacity=100"/> </a></div>]]></content:encoded>
			<wfw:commentRss>http://www.learningpython.com/2010/04/08/forums-forums-forums-2/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>AVC: Simplifying your GUI Code</title>
		<link>http://www.learningpython.com/2010/03/14/avc-simplifying-your-gui-code/</link>
		<comments>http://www.learningpython.com/2010/03/14/avc-simplifying-your-gui-code/#comments</comments>
		<pubDate>Sun, 14 Mar 2010 14:44:46 +0000</pubDate>
		<dc:creator>selsine</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[avc]]></category>
		<category><![CDATA[gui]]></category>
		<category><![CDATA[PyGTK]]></category>
		<category><![CDATA[PyQt]]></category>
		<category><![CDATA[python]]></category>
		<category><![CDATA[Python Magazine]]></category>
		<category><![CDATA[wxWidget]]></category>

		<guid isPermaLink="false">http://www.learningpython.com/?p=169</guid>
		<description><![CDATA[
			
				
			
		
Note: This article was first published the April 2008 issue of Python Magazine
By: Mark Mruss
GUI programming, like many other types of programming, can sometimes prove exhausting because you must repeat yourself over and over again. AVC is one tool available to Python GUI programmers that attempts to simplify things by synchronizing application data and GUI [...]]]></description>
			<content:encoded><![CDATA[<div class="tweetmeme_button" style="float: right; margin-left: 10px;">
			<a href="http://api.tweetmeme.com/share?url=http%3A%2F%2Fwww.learningpython.com%2F2010%2F03%2F14%2Favc-simplifying-your-gui-code%2F"><br />
				<img src="http://api.tweetmeme.com/imagebutton.gif?url=http%3A%2F%2Fwww.learningpython.com%2F2010%2F03%2F14%2Favc-simplifying-your-gui-code%2F&amp;style=normal" height="61" width="50" /><br />
			</a>
		</div>
<p>Note: This article was first published the <a href="http://www.pythonmagazine.com/c/issue/view/68">April 2008</a> issue of <a href="http://www.pythonmagazine.com/">Python Magazine</a></p>
<p><strong>By: Mark Mruss</strong></p>
<p>GUI programming, like many other types of programming, can sometimes prove exhausting because you must repeat yourself over and over again. <a href="http://avc.inrim.it/html/">AVC</a> is one tool available to Python GUI programmers that attempts to simplify things by synchronizing application data and GUI widgets.</p>
<h2>Introduction</h2>
<p>Every once in a while I find myself browsing the Internet trying to find out what&#8217;s new and exciting in the Python world. Sometimes I browse to find topics for this article; other times mere curiosity draws me across the web. While I was browsing the other day, I stumbled across <em>AVC: the Application View Controller</em> <a href="http://avc.inrim.it/html/">[1]</a>. I was immediately intrigued by it because its’ name is so similar to the Model View Controller (MVC) pattern. Being familiar with the Model View Controller pattern, and admittedly having  struggles with it in the past, I decided to check out AVC to determine if it might be a viable alternative.</p>
<p>After reading about AVC I was intrigued for several reasons. The main reason was the promise of &#8220;a multiplatform, fully automatic, live connection among graphical interface widgets and application variables.&#8221; <a href="http://avc.inrim.it/html/">[2]</a> This means that graphical widgets can be connected to variables and automatically synchronized. One of the (many?) problems with Graphical User Interface (GUI) programming is that you often find yourself doing the same thing over and over again. One of the things that you end of doing over and over again is setting the contents of a widget based on the value of a variable, and then subsequently, setting that variable&#8217;s value based on the current state of the widget. Whenever someone promises me an automatic connection between GUI widgets and my variables, I&#8217;m interested.</p>
<p><span id="more-169"></span></p>
<p>The other reason for investigating AVC is my past struggles with the Model View Controller pattern. I like the decoupling that the MVC pattern seems to provide, but I often feel as though I am needlessly duplicating code in order to stick with the pattern.  I looked into AVC hoping to find a simple framework that will avoid this and guide the separation of my application data from my GUI logic. However in the end, I realized that AVC (in its current state), does not appear to achieve this across all widget toolkits. It does allow you to separate your application from much of the GUI logic that one would normally need, but it does not appear to allow you to fully separate the data from the GUI.</p>
<p>AVC is being developed by Fabrizio Pollastri, and is released under version 3 of the GPL. I was unable to find much information about the project’s future or design objectives. But judging by the release notes, it is still being actively developed.  The project is only at version 0.5 so don’t be surprised if the API (Application Programming Interface) or some of the goals change.  Although relatively new, AVC bears further investigation because it already simplifies your GUI programming and contains the potential to do much more.  In this article, I will introduce some of the main concepts behind AVC, and provide a small, working example using AVC and PyGTK.</p>
<h2>Installing AVC</h2>
<p>AVC is a &#8220;Python module written in pure python&#8221; <a href="http://avc.inrim.it/html/">[3]</a>. This means that AVC is easy to install and does not have any dependencies aside from Python 2.2 or greater. You can download the current version (0.5.0) from the website or, if you are a lucky Linux user like me, you can install via your handy package manger.  If you download the source, you can install it after extraction, using the following command:</p>
<div class="hl-surround" style="height:28px;"><div class="hl-main"><pre><span class="hl-identifier">python setup</span><span class="hl-default">.</span><span class="hl-identifier">py install</span></pre></div></div>
<p>Depending on which widget toolkit you plan on using, the following requirements must also be met:</p>
<ul>
<li><strong>GTK+:</strong> PyGTK 2.8 &#8211; 2.10</li>
<li><strong>Qt:</strong> PyQt or PyQt4v3 &#8211; v4</li>
<li><strong>Tk:</strong> Tkinter 2.4</li>
<li><strong>wxWidgets:</strong> wxPython 2.6</li>
</ul>
<p>You can easily install any of the above toolkits using your favourite package manager, a source archive, or a binary installer found on each toolkit’s main website. Once AVC is installed, you can test the installation by importing the <code>avc</code> module from the interactive interpreter. If all goes well you will see something similar to the following:</p>
<div class="hl-surround" ><div class="hl-main"><pre><span class="hl-default">$ </span><span class="hl-identifier">python
Python </span><span class="hl-number">2.4.4 </span><span class="hl-brackets">(</span><span class="hl-comment">#2, Jan  3 2008, 13:36:28)
</span><span class="hl-brackets">[</span><span class="hl-identifier">GCC </span><span class="hl-number">4.2.3 20071123 </span><span class="hl-brackets">(</span><span class="hl-identifier">prerelease</span><span class="hl-brackets">) (</span><span class="hl-identifier">Debian </span><span class="hl-number">4.2.2</span><span class="hl-code">-</span><span class="hl-number">4</span><span class="hl-brackets">)] </span><span class="hl-identifier">on linux2
Type </span><span class="hl-quotes">&quot;</span><span class="hl-string">help</span><span class="hl-quotes">&quot;</span><span class="hl-code">, </span><span class="hl-quotes">&quot;</span><span class="hl-string">copyright</span><span class="hl-quotes">&quot;</span><span class="hl-code">, </span><span class="hl-quotes">&quot;</span><span class="hl-string">credits</span><span class="hl-quotes">&quot; </span><span class="hl-reserved">or </span><span class="hl-quotes">&quot;</span><span class="hl-string">license</span><span class="hl-quotes">&quot; </span><span class="hl-reserved">for </span><span class="hl-identifier">more information</span><span class="hl-code">.
&gt;&gt;&gt; </span><span class="hl-reserved">import </span><span class="hl-identifier">avc</span><span class="hl-code">
&gt;&gt;&gt;</span></pre></div></div>
<h2>Widget Support</h2>
<p>In its current state, AVC does not support all widgets available across all toolkits. It does currently support the following widgets:</p>
<ul>
<li>Button</li>
<li>Check Box</li>
<li>Combo Box (Not supported in Tk)</li>
<li>Entry</li>
<li>Label</li>
<li>Radio Button</li>
<li>Slider</li>
<li>Spin Button</li>
<li>Status Bar (Only supported by GTK+ and wxWidgets)</li>
<li>Text View</li>
<li>Toggle Button.</li>
</ul>
<p>The support of each of these widget types is then handled by specific widgets in each toolkit.</p>
<h2>Name-Matching</h2>
<p>In order to automatically synchronize variables and GUI widgets, AVC uses a name-matching technique. AVC supports two methods of name matching. The first method requires that the variable and the widget have the same name. For example, if you have a variable named <code>my_data</code> it will match with a widget also named <code>my_data</code>. In other words, if a variable and a widget have the same name they will be connected and their values synchronized.</p>
<p>The second name-matching technique allows you to connect variables to one or more widgets. Widgets can only be connected to one variable, but variables can be connected to any number of widgets. Using the second name-matching technique, you have a match if the widget name contains a double-underscore (<code>__</code>), <strong>and</strong> the portion before the double-underscore matches the variable name. For example, if you have variable named <code>my_numeric_value</code> and you want to match it with a Label widget and an Entry widget, you do this by naming the widgets as follows:</p>
<div class="hl-surround" ><div class="hl-main"><pre><span class="hl-identifier">my_numeric_value__label
my_numeric_value__entry</span></pre></div></div>
<p>Again, the text before the &#8220;__&#8221; must match the variable name, and the text after the &#8220;__&#8221; can be whatever you want to differentiate your widgets or ensure uniqueness (if the toolkit requires it).</p>
<h2>A GTK+, PyGTK, and AVC Example</h2>
<p>For this AVC example, I will use the GTK+ widget toolkit and PyGTK. PyGTK a &#8220;is a set of bindings to the GTK+ user interface toolkit for the Python language&#8221; <a href="http://faq.pygtk.org/index.py?req=all#1.1">[4]</a>. This means that it lets us write GUI applications in Python using the GTK+ widget toolkit. To avoid any flame wars: I did not choose GTK+ because it is the best toolkit but because it is the toolkit with which I am the most familiar.  In order to run this example you will need to have PyGTK 2.8 or later installed. You can get the latest version of PyGTK from the PyGTK website. <a href="http://www.pygtk.org/downloads.html">[5]</a></p>
<p>As I mentioned earlier, AVC works with many different widgets types. It also has many different features. I won&#8217;t be covering all of the features or widgets types in this column; if you are interesting in learning about some of these features or how to work with different widgets types, please see the AVC documentation. <a href="http://avc.inrim.it/doc/user_manual.pdf">[6]</a></p>
<p>This example is relatively simple, but it should illustrate some of the basic features of AVC. The example application asks for a person’s name and then displays that name in pop-up dialog. It will have the following features:</p>
<ol>
<li>A <code>gtk.TextView</code> widget to display the person&#8217;s name and allow the name to be edited. The <code>gtk.TextView</code> widget will be synchronised with a variable.</li>
<li>A <code>gtkButton</code> that will pop-up a <code>gtk.MessageDialog</code> to show the person&#8217;s name.</li>
<li>A <code>gtk.Button</code> that will reset the name to the name with which the application was initialized.</li>
</ol>
<p>To begin we need to import all of the modules necessary:</p>
<div class="hl-surround" ><div class="hl-main"><pre><span class="hl-reserved">import </span><span class="hl-identifier">gtk
</span><span class="hl-reserved">import </span><span class="hl-identifier">avc</span><span class="hl-default">.</span><span class="hl-identifier">avcgtk</span></pre></div></div>
<p><strong>Note</strong>: I am using a <code>gtk.TextView</code> widget instead of a <code>gtk.Entry</code> widget. In its current state, AVC does not propagate changes in <code>gtk.Entry</code> widgets back to the connected variable. I&#8217;m not sure if this is a current limitation or part of the design.</p>
<p>The above code imports the PyGTK module necessary to work with GTK+. It also imports the <code>avcgtk</code> module, which is used to link our &#8220;application variables&#8221; with our GTK+ GUI. Depending on what widget toolkit you use, you will have to use different modules. For example, if you are working with Qt4, you will import:</p>
<div class="hl-surround" style="height:28px;"><div class="hl-main"><pre><span class="hl-reserved">import </span><span class="hl-identifier">avc</span><span class="hl-default">.</span><span class="hl-identifier">avcqt4</span></pre></div></div>
<p>The next step is to create the &#8220;application&#8221; class. This will be the class that contains the data. In this example it will also create the GUI:</p>
<div class="hl-surround" style="height:28px;"><div class="hl-main"><pre><span class="hl-reserved">class </span><span class="hl-identifier">gtkAVC</span><span class="hl-brackets">(</span><span class="hl-identifier">avc</span><span class="hl-code">.</span><span class="hl-identifier">avcgtk</span><span class="hl-code">.</span><span class="hl-identifier">AVC</span><span class="hl-brackets">)</span><span class="hl-default">:</span></pre></div></div>
<p>Notice that we derive our application from the <code>avcgtk</code> module&#8217;s AVC class. This is the GTK+ specific AVC class with which we will work. We will also create an <code>__init__</code> method in the <code>gtkAVC</code> class. This is where we will initialize the data that will be connected to the GUI and create the GUI via the <code>init_gui</code> method:</p>
<div class="hl-surround" ><div class="hl-main"><pre><span class="hl-reserved">def </span><span class="hl-identifier">__init__</span><span class="hl-brackets">(</span><span class="hl-identifier">self</span><span class="hl-code">, </span><span class="hl-identifier">name</span><span class="hl-code">=</span><span class="hl-quotes">&quot;&quot;</span><span class="hl-brackets">)</span><span class="hl-default">:
    </span><span class="hl-comment">#set the variable and save the initial name
    </span><span class="hl-identifier">self</span><span class="hl-default">.</span><span class="hl-identifier">initial_name</span><span class="hl-default"> = </span><span class="hl-identifier">name
    self</span><span class="hl-default">.</span><span class="hl-identifier">name</span><span class="hl-default"> = </span><span class="hl-identifier">name
    </span><span class="hl-comment">#setup GUI
    </span><span class="hl-identifier">self</span><span class="hl-default">.</span><span class="hl-identifier">init_gui</span><span class="hl-brackets">()</span></pre></div></div>
<p>What we have here is pretty simple. We have the optional parameter <code>name</code> that we store as the current name and as the initial name. We then call the <code>init_gui</code> method that will create the GUI. The contents of the <code>init_gui</code> method can be seen in Listing 1. I won&#8217;t explain most of this code since the majority of it is PyGTK specific. However I will make note of several relevant segments below.</p>
<p><strong>Listing 1</strong></p>
<div class="hl-surround" style="height:280px;"><div class="hl-main"><pre><span class="hl-reserved">def </span><span class="hl-identifier">init_gui</span><span class="hl-brackets">(</span><span class="hl-identifier">self</span><span class="hl-brackets">)</span><span class="hl-default">:

    </span><span class="hl-comment">#Setup the window and the layout manager
    </span><span class="hl-identifier">self</span><span class="hl-default">.</span><span class="hl-identifier">window</span><span class="hl-default"> = </span><span class="hl-identifier">gtk</span><span class="hl-default">.</span><span class="hl-identifier">Window</span><span class="hl-brackets">()
    </span><span class="hl-identifier">self</span><span class="hl-default">.</span><span class="hl-identifier">window</span><span class="hl-default">.</span><span class="hl-identifier">connect</span><span class="hl-brackets">(</span><span class="hl-quotes">&quot;</span><span class="hl-string">destroy</span><span class="hl-quotes">&quot;</span><span class="hl-code">, </span><span class="hl-identifier">gtk</span><span class="hl-code">.</span><span class="hl-identifier">main_quit</span><span class="hl-brackets">)

    </span><span class="hl-identifier">self</span><span class="hl-default">.</span><span class="hl-identifier">h_layout</span><span class="hl-default"> = </span><span class="hl-identifier">gtk</span><span class="hl-default">.</span><span class="hl-identifier">HBox</span><span class="hl-brackets">()
    </span><span class="hl-identifier">self</span><span class="hl-default">.</span><span class="hl-identifier">window</span><span class="hl-default">.</span><span class="hl-identifier">add</span><span class="hl-brackets">(</span><span class="hl-identifier">self</span><span class="hl-code">.</span><span class="hl-identifier">h_layout</span><span class="hl-brackets">)

    </span><span class="hl-comment">#create the widgets
    </span><span class="hl-identifier">self</span><span class="hl-default">.</span><span class="hl-identifier">text_label</span><span class="hl-default"> = </span><span class="hl-identifier">gtk</span><span class="hl-default">.</span><span class="hl-identifier">Label</span><span class="hl-brackets">(</span><span class="hl-quotes">&quot;</span><span class="hl-string">Say hello:</span><span class="hl-quotes">&quot;</span><span class="hl-brackets">)
    </span><span class="hl-identifier">self</span><span class="hl-default">.</span><span class="hl-identifier">h_layout</span><span class="hl-default">.</span><span class="hl-identifier">add</span><span class="hl-brackets">(</span><span class="hl-identifier">self</span><span class="hl-code">.</span><span class="hl-identifier">text_label</span><span class="hl-brackets">)

    </span><span class="hl-identifier">self</span><span class="hl-default">.</span><span class="hl-identifier">frame</span><span class="hl-default"> = </span><span class="hl-identifier">gtk</span><span class="hl-default">.</span><span class="hl-identifier">Frame</span><span class="hl-brackets">()
    </span><span class="hl-identifier">self</span><span class="hl-default">.</span><span class="hl-identifier">h_layout</span><span class="hl-default">.</span><span class="hl-identifier">add</span><span class="hl-brackets">(</span><span class="hl-identifier">self</span><span class="hl-code">.</span><span class="hl-identifier">frame</span><span class="hl-brackets">)
    </span><span class="hl-identifier">self</span><span class="hl-default">.</span><span class="hl-identifier">scrolled_window</span><span class="hl-default"> = </span><span class="hl-identifier">gtk</span><span class="hl-default">.</span><span class="hl-identifier">ScrolledWindow</span><span class="hl-brackets">()
    </span><span class="hl-identifier">self</span><span class="hl-default">.</span><span class="hl-identifier">frame</span><span class="hl-default">.</span><span class="hl-identifier">add</span><span class="hl-brackets">(</span><span class="hl-identifier">self</span><span class="hl-code">.</span><span class="hl-identifier">scrolled_window</span><span class="hl-brackets">)

    </span><span class="hl-identifier">self</span><span class="hl-default">.</span><span class="hl-identifier">text_view</span><span class="hl-default"> = </span><span class="hl-identifier">gtk</span><span class="hl-default">.</span><span class="hl-identifier">TextView</span><span class="hl-brackets">()
    </span><span class="hl-identifier">self</span><span class="hl-default">.</span><span class="hl-identifier">text_view</span><span class="hl-default">.</span><span class="hl-identifier">set_name</span><span class="hl-brackets">(</span><span class="hl-quotes">&quot;</span><span class="hl-string">name__text_view</span><span class="hl-quotes">&quot;</span><span class="hl-brackets">)
    </span><span class="hl-identifier">self</span><span class="hl-default">.</span><span class="hl-identifier">scrolled_window</span><span class="hl-default">.</span><span class="hl-identifier">add</span><span class="hl-brackets">(</span><span class="hl-identifier">self</span><span class="hl-code">.</span><span class="hl-identifier">text_view</span><span class="hl-brackets">)

    </span><span class="hl-identifier">self</span><span class="hl-default">.</span><span class="hl-identifier">hello_button</span><span class="hl-default"> = </span><span class="hl-identifier">gtk</span><span class="hl-default">.</span><span class="hl-identifier">Button</span><span class="hl-brackets">(</span><span class="hl-quotes">&quot;</span><span class="hl-string">Hello!</span><span class="hl-quotes">&quot;</span><span class="hl-brackets">)
    </span><span class="hl-identifier">self</span><span class="hl-default">.</span><span class="hl-identifier">hello_button</span><span class="hl-default">.</span><span class="hl-identifier">connect</span><span class="hl-brackets">(</span><span class="hl-quotes">&quot;</span><span class="hl-string">clicked</span><span class="hl-quotes">&quot;</span><span class="hl-code">, </span><span class="hl-identifier">self</span><span class="hl-code">.</span><span class="hl-identifier">on_hello_clicked</span><span class="hl-brackets">)
    </span><span class="hl-identifier">self</span><span class="hl-default">.</span><span class="hl-identifier">h_layout</span><span class="hl-default">.</span><span class="hl-identifier">add</span><span class="hl-brackets">(</span><span class="hl-identifier">self</span><span class="hl-code">.</span><span class="hl-identifier">hello_button</span><span class="hl-brackets">)

    </span><span class="hl-identifier">self</span><span class="hl-default">.</span><span class="hl-identifier">reset_button</span><span class="hl-default"> = </span><span class="hl-identifier">gtk</span><span class="hl-default">.</span><span class="hl-identifier">Button</span><span class="hl-brackets">(</span><span class="hl-quotes">&quot;</span><span class="hl-string">Reset</span><span class="hl-quotes">&quot;</span><span class="hl-brackets">)
    </span><span class="hl-identifier">self</span><span class="hl-default">.</span><span class="hl-identifier">reset_button</span><span class="hl-default">.</span><span class="hl-identifier">connect</span><span class="hl-brackets">(</span><span class="hl-quotes">&quot;</span><span class="hl-string">clicked</span><span class="hl-quotes">&quot;</span><span class="hl-code">, </span><span class="hl-identifier">self</span><span class="hl-code">.</span><span class="hl-identifier">on_reset_clicked</span><span class="hl-brackets">)
    </span><span class="hl-identifier">self</span><span class="hl-default">.</span><span class="hl-identifier">h_layout</span><span class="hl-default">.</span><span class="hl-identifier">add</span><span class="hl-brackets">(</span><span class="hl-identifier">self</span><span class="hl-code">.</span><span class="hl-identifier">reset_button</span><span class="hl-brackets">)

    </span><span class="hl-identifier">self</span><span class="hl-default">.</span><span class="hl-identifier">window</span><span class="hl-default">.</span><span class="hl-identifier">show_all</span><span class="hl-brackets">()</span></pre></div></div>
<p>The only AVC specific code segment in the <code>init_gui</code> function is where we set the name of the <code>gtk.TextView</code> widget:</p>
<div class="hl-surround" style="height:28px;"><div class="hl-main"><pre><span class="hl-identifier">self</span><span class="hl-default">.</span><span class="hl-identifier">text_view</span><span class="hl-default">.</span><span class="hl-identifier">set_name</span><span class="hl-brackets">(</span><span class="hl-quotes">&quot;</span><span class="hl-string">name__text_view</span><span class="hl-quotes">&quot;</span><span class="hl-brackets">)</span></pre></div></div>
<p>This is all the code that we need to connect the <code>gtk.TextView</code> widget with the <code>name</code> variable that we created at the beginning of the <code>__init__</code> function. (Now, how&#8217;s that for simple?) Notice that the <code>name</code> section of the &#8220;name__text_view&#8221; string will match with the <code>self.name</code> variable. It is also important to note that the variable and the widget are not yet connected. They will become connected when the <code>avc_init</code> method is called.</p>
<p>The other non-AVC related code of note is the connection of both <code>gtk.Button</code> widgets’ clicked signals with signal handlers. We connect the &#8220;hello&#8221; button to the <code>on_hello_clicked</code> method and the &#8220;reset&#8221; button to the <code>on_reset_clicked</code> method.</p>
<p>That&#8217;s it for the <code>init_gui</code> function, now let&#8217;s look at the two signal handlers. The <code>on_hello_clicked</code> method, shown in Listing 2, simply displays the name in a <code>gtk.MessageDialog</code>. What should be interesting to GUI programmers about this function is that instead of reading the data from the <code>gtk.TextView</code> widget, we simply reference <code>self.name</code> for the dialog&#8217;s text. We can do this because <code>self.name</code> and the <code>gtk.TextView</code> widget are connected and their values are always the same.</p>
<p><strong>Listing 2</strong></p>
<div class="hl-surround" ><div class="hl-main"><pre><span class="hl-reserved">def </span><span class="hl-identifier">on_hello_clicked</span><span class="hl-brackets">(</span><span class="hl-identifier">self</span><span class="hl-code">, </span><span class="hl-identifier">widget</span><span class="hl-brackets">)</span><span class="hl-default">:
    </span><span class="hl-reserved">def </span><span class="hl-identifier">close</span><span class="hl-brackets">(</span><span class="hl-identifier">dialog</span><span class="hl-code">, </span><span class="hl-identifier">response</span><span class="hl-brackets">)</span><span class="hl-default">:
        </span><span class="hl-comment">#Close the dialog on ok
        </span><span class="hl-identifier">dialog</span><span class="hl-default">.</span><span class="hl-identifier">destroy</span><span class="hl-brackets">()
    </span><span class="hl-identifier">message_dlg</span><span class="hl-default"> = </span><span class="hl-identifier">gtk</span><span class="hl-default">.</span><span class="hl-identifier">MessageDialog</span><span class="hl-brackets">(</span><span class="hl-identifier">self</span><span class="hl-code">.</span><span class="hl-identifier">window</span><span class="hl-code">
        , </span><span class="hl-number">0</span><span class="hl-code">
        , </span><span class="hl-identifier">gtk</span><span class="hl-code">.</span><span class="hl-identifier">MESSAGE_INFO</span><span class="hl-code">
        , </span><span class="hl-identifier">gtk</span><span class="hl-code">.</span><span class="hl-identifier">BUTTONS_OK</span><span class="hl-code">
        , </span><span class="hl-brackets">(</span><span class="hl-quotes">&quot;</span><span class="hl-string">Hello: %s</span><span class="hl-quotes">&quot;</span><span class="hl-code"> % </span><span class="hl-identifier">self</span><span class="hl-code">.</span><span class="hl-identifier">name</span><span class="hl-brackets">))
    </span><span class="hl-identifier">message_dlg</span><span class="hl-default">.</span><span class="hl-identifier">connect</span><span class="hl-brackets">(</span><span class="hl-quotes">&quot;</span><span class="hl-string">response</span><span class="hl-quotes">&quot;</span><span class="hl-code">, </span><span class="hl-identifier">close</span><span class="hl-brackets">)
    </span><span class="hl-identifier">message_dlg</span><span class="hl-default">.</span><span class="hl-identifier">run</span><span class="hl-brackets">()</span></pre></div></div>
<p>The <code>on_reset_clicked</code> function is also very simple and straightforward. We simply reset the name to the initial name:</p>
<div class="hl-surround" ><div class="hl-main"><pre><span class="hl-reserved">def </span><span class="hl-identifier">on_reset_clicked</span><span class="hl-brackets">(</span><span class="hl-identifier">self</span><span class="hl-code">, </span><span class="hl-identifier">widget</span><span class="hl-brackets">)</span><span class="hl-default">:
    </span><span class="hl-comment">#Reset the name to the initial name
    </span><span class="hl-identifier">self</span><span class="hl-default">.</span><span class="hl-identifier">name</span><span class="hl-default"> = </span><span class="hl-identifier">self</span><span class="hl-default">.</span><span class="hl-identifier">initial_name</span></pre></div></div>
<p>Again, notice that we don&#8217;t have to worry about doing anything to the <code>gtk.TextView</code> widget that displays the current name. By simply modifying the data, what is displayed in the GUI will automatically be updated by AVC.</p>
<p>The next and final step in our test application is to create our class instances and actually show the GUI:</p>
<div class="hl-surround" ><div class="hl-main"><pre><span class="hl-identifier">if </span><span class="hl-brackets">(</span><span class="hl-identifier">__name__</span><span class="hl-code"> == </span><span class="hl-quotes">&quot;</span><span class="hl-string">__main__</span><span class="hl-quotes">&quot;</span><span class="hl-brackets">)</span><span class="hl-default">:
    </span><span class="hl-identifier">gtk_avc</span><span class="hl-default"> = </span><span class="hl-identifier">gtkAVC</span><span class="hl-brackets">(</span><span class="hl-quotes">&quot;</span><span class="hl-string">Mark Mruss</span><span class="hl-quotes">&quot;</span><span class="hl-brackets">)
    </span><span class="hl-identifier">gtk_avc</span><span class="hl-default">.</span><span class="hl-identifier">avc_init</span><span class="hl-brackets">()
    </span><span class="hl-identifier">gtk</span><span class="hl-default">.</span><span class="hl-identifier">main</span><span class="hl-brackets">()</span></pre></div></div>
<p>Since I am working in a Python file, I perform a simple test to make sure that the file is being launched directly instead of being imported as a module. I then create an instance of the <code>gtkAVC</code> class setting the name to be my name. The <code>avc_init</code> method is then called (which is a member of the <code>avc.avcgtk.AVC</code> class). The <code>avc_init</code> method is where all of the magic happens.  It is where AVC goes through an application&#8217;s variables and connects them to the GUI widgets based upon the name matching technique explained earlier. <code>avc_init</code> must be called <strong>after</strong> all of the data in the &#8220;application&#8221; and the widgets have been created.</p>
<p>The final step in this example, is to run the <code>gtk.main</code> function. This is the &#8220;main loop&#8221; of our PyGTK based application and is standard when working with PyGTK.</p>
<p>The entire code can be seen in Listing 3. When you run the code you will be greeted with something similar to Figure 1. It may not seem like much, but what we have here is a fully functional AVC &#8220;application&#8221;. This simple &#8220;application&#8221; illustrates how easy it is to create an automatic connection between your data and your GUI.</p>
<div id="attachment_172" class="wp-caption alignnone" style="width: 310px"><img src="http://www.learningpython.com/wp-content/uploads/2010/03/Figure1-300x230.png" alt="Figure1" title="Figure1" width="300" height="230" class="size-medium wp-image-172" /><p class="wp-caption-text">Figure1</p></div>
<p><strong>Listing 3</strong></p>
<div class="hl-surround" style="height:280px;"><div class="hl-main"><pre><span class="hl-comment">#! /usr/bin/env python
</span><span class="hl-reserved">import </span><span class="hl-identifier">gtk
</span><span class="hl-reserved">import </span><span class="hl-identifier">avc</span><span class="hl-default">.</span><span class="hl-identifier">avcgtk

</span><span class="hl-reserved">class </span><span class="hl-identifier">gtkAVC</span><span class="hl-brackets">(</span><span class="hl-identifier">avc</span><span class="hl-code">.</span><span class="hl-identifier">avcgtk</span><span class="hl-code">.</span><span class="hl-identifier">AVC</span><span class="hl-brackets">)</span><span class="hl-default">:

    </span><span class="hl-reserved">def </span><span class="hl-identifier">__init__</span><span class="hl-brackets">(</span><span class="hl-identifier">self</span><span class="hl-code">, </span><span class="hl-identifier">name</span><span class="hl-code">=</span><span class="hl-quotes">&quot;&quot;</span><span class="hl-brackets">)</span><span class="hl-default">:
        </span><span class="hl-comment">#set the variable and save the initial name
        </span><span class="hl-identifier">self</span><span class="hl-default">.</span><span class="hl-identifier">initial_name</span><span class="hl-default"> = </span><span class="hl-identifier">name
        self</span><span class="hl-default">.</span><span class="hl-identifier">name</span><span class="hl-default"> = </span><span class="hl-identifier">name
        </span><span class="hl-comment">#setup GUI
        </span><span class="hl-identifier">self</span><span class="hl-default">.</span><span class="hl-identifier">init_gui</span><span class="hl-brackets">()

    </span><span class="hl-reserved">def </span><span class="hl-identifier">init_gui</span><span class="hl-brackets">(</span><span class="hl-identifier">self</span><span class="hl-brackets">)</span><span class="hl-default">:

        </span><span class="hl-comment">#Setup the window and the layout manager
        </span><span class="hl-identifier">self</span><span class="hl-default">.</span><span class="hl-identifier">window</span><span class="hl-default"> = </span><span class="hl-identifier">gtk</span><span class="hl-default">.</span><span class="hl-identifier">Window</span><span class="hl-brackets">()
        </span><span class="hl-identifier">self</span><span class="hl-default">.</span><span class="hl-identifier">window</span><span class="hl-default">.</span><span class="hl-identifier">connect</span><span class="hl-brackets">(</span><span class="hl-quotes">&quot;</span><span class="hl-string">destroy</span><span class="hl-quotes">&quot;</span><span class="hl-code">, </span><span class="hl-identifier">gtk</span><span class="hl-code">.</span><span class="hl-identifier">main_quit</span><span class="hl-brackets">)

        </span><span class="hl-identifier">self</span><span class="hl-default">.</span><span class="hl-identifier">h_layout</span><span class="hl-default"> = </span><span class="hl-identifier">gtk</span><span class="hl-default">.</span><span class="hl-identifier">HBox</span><span class="hl-brackets">()
        </span><span class="hl-identifier">self</span><span class="hl-default">.</span><span class="hl-identifier">window</span><span class="hl-default">.</span><span class="hl-identifier">add</span><span class="hl-brackets">(</span><span class="hl-identifier">self</span><span class="hl-code">.</span><span class="hl-identifier">h_layout</span><span class="hl-brackets">)

        </span><span class="hl-comment">#create the widgets
        </span><span class="hl-identifier">self</span><span class="hl-default">.</span><span class="hl-identifier">text_label</span><span class="hl-default"> = </span><span class="hl-identifier">gtk</span><span class="hl-default">.</span><span class="hl-identifier">Label</span><span class="hl-brackets">(</span><span class="hl-quotes">&quot;</span><span class="hl-string">Say hello:</span><span class="hl-quotes">&quot;</span><span class="hl-brackets">)
        </span><span class="hl-identifier">self</span><span class="hl-default">.</span><span class="hl-identifier">h_layout</span><span class="hl-default">.</span><span class="hl-identifier">add</span><span class="hl-brackets">(</span><span class="hl-identifier">self</span><span class="hl-code">.</span><span class="hl-identifier">text_label</span><span class="hl-brackets">)

        </span><span class="hl-identifier">self</span><span class="hl-default">.</span><span class="hl-identifier">frame</span><span class="hl-default"> = </span><span class="hl-identifier">gtk</span><span class="hl-default">.</span><span class="hl-identifier">Frame</span><span class="hl-brackets">()
        </span><span class="hl-identifier">self</span><span class="hl-default">.</span><span class="hl-identifier">h_layout</span><span class="hl-default">.</span><span class="hl-identifier">add</span><span class="hl-brackets">(</span><span class="hl-identifier">self</span><span class="hl-code">.</span><span class="hl-identifier">frame</span><span class="hl-brackets">)
        </span><span class="hl-identifier">self</span><span class="hl-default">.</span><span class="hl-identifier">scrolled_window</span><span class="hl-default"> = </span><span class="hl-identifier">gtk</span><span class="hl-default">.</span><span class="hl-identifier">ScrolledWindow</span><span class="hl-brackets">()
        </span><span class="hl-identifier">self</span><span class="hl-default">.</span><span class="hl-identifier">frame</span><span class="hl-default">.</span><span class="hl-identifier">add</span><span class="hl-brackets">(</span><span class="hl-identifier">self</span><span class="hl-code">.</span><span class="hl-identifier">scrolled_window</span><span class="hl-brackets">)

        </span><span class="hl-identifier">self</span><span class="hl-default">.</span><span class="hl-identifier">text_view</span><span class="hl-default"> = </span><span class="hl-identifier">gtk</span><span class="hl-default">.</span><span class="hl-identifier">TextView</span><span class="hl-brackets">()
        </span><span class="hl-identifier">self</span><span class="hl-default">.</span><span class="hl-identifier">text_view</span><span class="hl-default">.</span><span class="hl-identifier">set_name</span><span class="hl-brackets">(</span><span class="hl-quotes">&quot;</span><span class="hl-string">name__text_view</span><span class="hl-quotes">&quot;</span><span class="hl-brackets">)
        </span><span class="hl-identifier">self</span><span class="hl-default">.</span><span class="hl-identifier">scrolled_window</span><span class="hl-default">.</span><span class="hl-identifier">add</span><span class="hl-brackets">(</span><span class="hl-identifier">self</span><span class="hl-code">.</span><span class="hl-identifier">text_view</span><span class="hl-brackets">)

        </span><span class="hl-identifier">self</span><span class="hl-default">.</span><span class="hl-identifier">hello_button</span><span class="hl-default"> = </span><span class="hl-identifier">gtk</span><span class="hl-default">.</span><span class="hl-identifier">Button</span><span class="hl-brackets">(</span><span class="hl-quotes">&quot;</span><span class="hl-string">Hello!</span><span class="hl-quotes">&quot;</span><span class="hl-brackets">)
        </span><span class="hl-identifier">self</span><span class="hl-default">.</span><span class="hl-identifier">hello_button</span><span class="hl-default">.</span><span class="hl-identifier">connect</span><span class="hl-brackets">(</span><span class="hl-quotes">&quot;</span><span class="hl-string">clicked</span><span class="hl-quotes">&quot;</span><span class="hl-code">, </span><span class="hl-identifier">self</span><span class="hl-code">.</span><span class="hl-identifier">on_hello_clicked</span><span class="hl-brackets">)
        </span><span class="hl-identifier">self</span><span class="hl-default">.</span><span class="hl-identifier">h_layout</span><span class="hl-default">.</span><span class="hl-identifier">add</span><span class="hl-brackets">(</span><span class="hl-identifier">self</span><span class="hl-code">.</span><span class="hl-identifier">hello_button</span><span class="hl-brackets">)

        </span><span class="hl-identifier">self</span><span class="hl-default">.</span><span class="hl-identifier">reset_button</span><span class="hl-default"> = </span><span class="hl-identifier">gtk</span><span class="hl-default">.</span><span class="hl-identifier">Button</span><span class="hl-brackets">(</span><span class="hl-quotes">&quot;</span><span class="hl-string">Reset</span><span class="hl-quotes">&quot;</span><span class="hl-brackets">)
        </span><span class="hl-identifier">self</span><span class="hl-default">.</span><span class="hl-identifier">reset_button</span><span class="hl-default">.</span><span class="hl-identifier">connect</span><span class="hl-brackets">(</span><span class="hl-quotes">&quot;</span><span class="hl-string">clicked</span><span class="hl-quotes">&quot;</span><span class="hl-code">, </span><span class="hl-identifier">self</span><span class="hl-code">.</span><span class="hl-identifier">on_reset_clicked</span><span class="hl-brackets">)
        </span><span class="hl-identifier">self</span><span class="hl-default">.</span><span class="hl-identifier">h_layout</span><span class="hl-default">.</span><span class="hl-identifier">add</span><span class="hl-brackets">(</span><span class="hl-identifier">self</span><span class="hl-code">.</span><span class="hl-identifier">reset_button</span><span class="hl-brackets">)

        </span><span class="hl-identifier">self</span><span class="hl-default">.</span><span class="hl-identifier">window</span><span class="hl-default">.</span><span class="hl-identifier">show_all</span><span class="hl-brackets">()

    </span><span class="hl-reserved">def </span><span class="hl-identifier">on_hello_clicked</span><span class="hl-brackets">(</span><span class="hl-identifier">self</span><span class="hl-code">, </span><span class="hl-identifier">widget</span><span class="hl-brackets">)</span><span class="hl-default">:
        </span><span class="hl-reserved">def </span><span class="hl-identifier">close</span><span class="hl-brackets">(</span><span class="hl-identifier">dialog</span><span class="hl-code">, </span><span class="hl-identifier">response</span><span class="hl-brackets">)</span><span class="hl-default">:
            </span><span class="hl-comment">#Close the dialog on ok
            </span><span class="hl-identifier">dialog</span><span class="hl-default">.</span><span class="hl-identifier">destroy</span><span class="hl-brackets">()
        </span><span class="hl-identifier">message_dlg</span><span class="hl-default"> = </span><span class="hl-identifier">gtk</span><span class="hl-default">.</span><span class="hl-identifier">MessageDialog</span><span class="hl-brackets">(</span><span class="hl-identifier">self</span><span class="hl-code">.</span><span class="hl-identifier">window</span><span class="hl-code">
            , </span><span class="hl-number">0</span><span class="hl-code">
            , </span><span class="hl-identifier">gtk</span><span class="hl-code">.</span><span class="hl-identifier">MESSAGE_INFO</span><span class="hl-code">
            , </span><span class="hl-identifier">gtk</span><span class="hl-code">.</span><span class="hl-identifier">BUTTONS_OK</span><span class="hl-code">
            , </span><span class="hl-brackets">(</span><span class="hl-quotes">&quot;</span><span class="hl-string">Hello: %s</span><span class="hl-quotes">&quot;</span><span class="hl-code"> % </span><span class="hl-identifier">self</span><span class="hl-code">.</span><span class="hl-identifier">name</span><span class="hl-brackets">))
        </span><span class="hl-identifier">message_dlg</span><span class="hl-default">.</span><span class="hl-identifier">connect</span><span class="hl-brackets">(</span><span class="hl-quotes">&quot;</span><span class="hl-string">response</span><span class="hl-quotes">&quot;</span><span class="hl-code">, </span><span class="hl-identifier">close</span><span class="hl-brackets">)
        </span><span class="hl-identifier">message_dlg</span><span class="hl-default">.</span><span class="hl-identifier">run</span><span class="hl-brackets">()

    </span><span class="hl-reserved">def </span><span class="hl-identifier">on_reset_clicked</span><span class="hl-brackets">(</span><span class="hl-identifier">self</span><span class="hl-code">, </span><span class="hl-identifier">widget</span><span class="hl-brackets">)</span><span class="hl-default">:
        </span><span class="hl-comment">#Reset the name to the initial name
        </span><span class="hl-identifier">self</span><span class="hl-default">.</span><span class="hl-identifier">name</span><span class="hl-default"> = </span><span class="hl-identifier">self</span><span class="hl-default">.</span><span class="hl-identifier">initial_name

if </span><span class="hl-brackets">(</span><span class="hl-identifier">__name__</span><span class="hl-code"> == </span><span class="hl-quotes">&quot;</span><span class="hl-string">__main__</span><span class="hl-quotes">&quot;</span><span class="hl-brackets">)</span><span class="hl-default">:
    </span><span class="hl-identifier">gtk_avc</span><span class="hl-default"> = </span><span class="hl-identifier">gtkAVC</span><span class="hl-brackets">(</span><span class="hl-quotes">&quot;</span><span class="hl-string">Mark Mruss</span><span class="hl-quotes">&quot;</span><span class="hl-brackets">)
    </span><span class="hl-identifier">gtk_avc</span><span class="hl-default">.</span><span class="hl-identifier">avc_init</span><span class="hl-brackets">()
    </span><span class="hl-identifier">gtk</span><span class="hl-default">.</span><span class="hl-identifier">main</span><span class="hl-brackets">()</span></pre></div></div>
<h2>Benefits and Limitations</h2>
<p>For a project that is little more than one year old (the first release was in January 2007) AVC appears quite stable and ready to be used. This is not to say that AVC is perfect. I did encounter a few issues.</p>
<p>The most notable issue that I encountered is the tightly coupled structure that AVC seems to impose on your application. For a module that tries to simplify the relationship between application data and GUI&#8217;s, this feels like a bit of an issue because. For example, when testing using PyGTK I was able to easily separate the GUI and the &#8220;application&#8221; into separate classes. But when I tried to do the same thing using PyQt4, I encountered an error because the <code>avc_timer</code> function in the <code>avc.avcqt4.AVC</code> module expects that the &#8220;application&#8221; class is itself a <code>QObject</code> (namely the actual <code>QApplication</code>). I find this counterintuitive since being able to separate the data from the GUI-logic seems to be a goal of AVC and similar tools. If you are able to separate the &#8220;application&#8221; fully from the GUI, you can easily connect your &#8220;application&#8221; to different GUI&#8217;s, and (by changing the AVC base class) even different widget toolkits.</p>
<p>I would also be interested in the ability to connect more types of data to more types of widgets. For example, I am interested in synchronizing Python lists with the contents of List boxes and Combo boxes. This is in addition to the current ability to synchronize the selection in the two widgets with integers.</p>
<p>Of course AVC also has a lot going for it. For one, I really like that AVC works with different widget toolkits. I have not seen this very often. It is a real benefit, especially when it comes to people adopting AVC. Hopefully in the future AVC will allow for further separation of the data and the GUI, truly enabling us to use different GUI&#8217;s and different widget toolkits with our data.</p>
<p>What I like most about AVC is its simplicity. I have played around with similar solutions and AVC is one of the leaders in terms of ease of use. I was able to get create a simple AVC based application in almost no time at all. (The time that it did take was spent trying to remember PyGTK.) Much of this has to do with the streamlined nature of AVC. There is very little to configure regardless of what widget toolkit you use. While this simplicity limits what AVC can currently achieve compared to other solutions, it also makes the barrier to entry low and the usage trivial. User friendliness is certainly a good thing in a package that aims to make GUI application development easier.</p>
<h2>Conclusion</h2>
<p>While the data that we worked with in the earlier example wasn&#8217;t that complicated (a simple string), I hope that it illustrates how helpful AVC is if you are working with a large amount of data or data that could be updated by an external source. Instead of having to worry about what widgets or toolkits the data was being displayed in, AVC lets us work with the data and GUI transparently, leaving the synchronization to AVC.</p>
<p>If what AVC offers sounds interesting to you, download it from the AVC website and try it out.  Although it it&#8217;s not there just yet with enough attention, usage, and contributions from the Python community, AVC should reach full-feature status in no time.</p>
<p><a href="http://avc.inrim.it/html/">[1] http://avc.inrim.it/html/</a><br />
<a href="http://avc.inrim.it/html/">[2] http://avc.inrim.it/html/</a><br />
<a href="http://avc.inrim.it/html/">[3] http://avc.inrim.it/html/</a><br />
<a href="http://faq.pygtk.org/index.py?req=all#1.1">[4] http://faq.pygtk.org/index.py?req=all#1.1</a><br />
<a href="http://www.pygtk.org/downloads.html">[5] http://www.pygtk.org/downloads.html</a><br />
<a href="http://avc.inrim.it/doc/user_manual.pdf">[6] http://avc.inrim.it/doc/user_manual.pdf</a></p>
<p><strong>Note:</strong> If you haven&#8217;t already, please check out my <a href="http://www.learningpython.com/2010/03/04/poll-python-version/">Python version poll</a>.</p>
<div style="float:right;margin:0px 0px 0px 0px;"><a href="http://www.google.com/reader/link?url=http://www.learningpython.com/2010/03/14/avc-simplifying-your-gui-code/&title=AVC: Simplifying your GUI Code&srcTitle=learning python&srcURL=http://www.learningpython.com"target="_blank" rel=""><img border="0" src="http://www.learningpython.com/wp-content/plugins/wp-google-buzz/icon/12.png" style="opacity:1;filter:alpha(opacity=100)" onmouseover="this.style.opacity=0.8;this.filters.alpha.opacity=70" onmouseout="this.style.opacity=1;this.filters.alpha.opacity=100"/> </a></div>]]></content:encoded>
			<wfw:commentRss>http://www.learningpython.com/2010/03/14/avc-simplifying-your-gui-code/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Poll: Python Version</title>
		<link>http://www.learningpython.com/2010/03/04/poll-python-version/</link>
		<comments>http://www.learningpython.com/2010/03/04/poll-python-version/#comments</comments>
		<pubDate>Fri, 05 Mar 2010 03:52:10 +0000</pubDate>
		<dc:creator>selsine</dc:creator>
				<category><![CDATA[Poll]]></category>
		<category><![CDATA[python]]></category>

		<guid isPermaLink="false">http://www.learningpython.com/?p=154</guid>
		<description><![CDATA[
			
				
			
		
Edit: Due to popular demand (well a couple of comments) I&#8217;ve decided to allow multiple answers to the poll. This should make everyone that uses two versions happy.
With two major versions of Python available to us Python programmers (2.X and 3.X) I thought it would be interesting to see which version the readers of this [...]]]></description>
			<content:encoded><![CDATA[<div class="tweetmeme_button" style="float: right; margin-left: 10px;">
			<a href="http://api.tweetmeme.com/share?url=http%3A%2F%2Fwww.learningpython.com%2F2010%2F03%2F04%2Fpoll-python-version%2F"><br />
				<img src="http://api.tweetmeme.com/imagebutton.gif?url=http%3A%2F%2Fwww.learningpython.com%2F2010%2F03%2F04%2Fpoll-python-version%2F&amp;style=normal" height="61" width="50" /><br />
			</a>
		</div>
<p><strong>Edit:</strong> Due to popular demand (well a couple of comments) I&#8217;ve decided to allow multiple answers to the poll. This should make everyone that uses two versions happy.</p>
<p>With two major versions of Python available to us Python programmers (<a href="http://docs.python.org/">2.X</a> and <a href="http://docs.python.org/3.1/index.html">3.X</a>) I thought it would be interesting to see which version the readers of this blog are using and targeting. </p>
<p>Personally I&#8217;m still using 2.5 on my Debian box because it&#8217;s the default, and 2.6 on my Windows PC.  While I have used 3.X and have it installed, I&#8217;ve remained on the 2.X branch largely because many of the modules that I play around with are still focused on the 2.X branch so that&#8217;s where my focus has remained. </p>
<p>I voted 2.5 since I do that majority of my programing on my Debian box. So now what about you: Note: There is a poll embedded within this post, please visit the site to participate in this post's poll.</p>
<p>If you want to explain your choice leave a comment below.</p>
<div style="float:right;margin:0px 0px 0px 0px;"><a href="http://www.google.com/reader/link?url=http://www.learningpython.com/2010/03/04/poll-python-version/&title=Poll: Python Version&srcTitle=learning python&srcURL=http://www.learningpython.com"target="_blank" rel=""><img border="0" src="http://www.learningpython.com/wp-content/plugins/wp-google-buzz/icon/12.png" style="opacity:1;filter:alpha(opacity=100)" onmouseover="this.style.opacity=0.8;this.filters.alpha.opacity=70" onmouseout="this.style.opacity=1;this.filters.alpha.opacity=100"/> </a></div>]]></content:encoded>
			<wfw:commentRss>http://www.learningpython.com/2010/03/04/poll-python-version/feed/</wfw:commentRss>
		<slash:comments>14</slash:comments>
		</item>
		<item>
		<title>An Introduction to Google Calendars</title>
		<link>http://www.learningpython.com/2010/02/27/an-introduction-to-google-calendars/</link>
		<comments>http://www.learningpython.com/2010/02/27/an-introduction-to-google-calendars/#comments</comments>
		<pubDate>Sat, 27 Feb 2010 05:14:18 +0000</pubDate>
		<dc:creator>selsine</dc:creator>
				<category><![CDATA[Python Magazine]]></category>
		<category><![CDATA[python]]></category>

		<guid isPermaLink="false">http://www.learningpython.com/?p=135</guid>
		<description><![CDATA[
			
				
			
		
Note: This article was first published the March 2008 issue of Python Magazine
Mark Mruss
Over the past few years Google has expanded it&#8217;s services beyond those of a normal search engine. One of those new services is the Google Calendar. This article will provide an introduction to working with the Google Calendar using Python.
Introduction
As many of [...]]]></description>
			<content:encoded><![CDATA[<div class="tweetmeme_button" style="float: right; margin-left: 10px;">
			<a href="http://api.tweetmeme.com/share?url=http%3A%2F%2Fwww.learningpython.com%2F2010%2F02%2F27%2Fan-introduction-to-google-calendars%2F"><br />
				<img src="http://api.tweetmeme.com/imagebutton.gif?url=http%3A%2F%2Fwww.learningpython.com%2F2010%2F02%2F27%2Fan-introduction-to-google-calendars%2F&amp;style=normal" height="61" width="50" /><br />
			</a>
		</div>
<p>Note: This article was first published the <a href="http://www.pythonmagazine.com/c/issue/view/67">March 2008</a> issue of <a href="http://www.pythonmagazine.com/">Python Magazine</a></p>
<p><strong>Mark Mruss</strong></p>
<p>Over the past few years Google has expanded it&#8217;s services beyond those of a normal search engine. One of those new services is the Google Calendar. This article will provide an introduction to working with the Google Calendar using Python.</p>
<h2>Introduction</h2>
<p>As many of you know, Google has branched out and started offering more services besides their ubiquitous search engine. You have email, calendars, documents, spreadsheets, photos, maps, videos, source code hosting, and the list goes on. Fortunately for us Python programmers, Google released the Google data Python Client Library on March 26th, 2007, giving Python programmers easy access to some of these services.</p>
<p><span id="more-135"></span></p>
<p>What the Google data Python Client Library, or &#8220;gdata-python-client&#8221;, does is provide &#8220;a library and source code that makes it easy to access data through Google Data APIs.&#8221; <a href="http://code.google.com/p/gdata-python-client/">[1]</a> This leads to the question: &#8220;what are the Google Data APIs?&#8221; In the words of Google: &#8220;The Google data APIs provide a simple standard protocol for reading and writing data on the web. These APIs use either of two standard XML-based syndication formats: Atom or RSS.&#8221;<a href="http://code.google.com/apis/gdata/index.html">[2]</a></p>
<p>The Google services that use the Google data APIs include many of the services that we have grown to know and love:</p>
<ul>
<li>Google Apps</li>
<li>Google Base</li>
<li>Blogger</li>
<li>Google Calendar</li>
<li>Google Code Search</li>
<li>Google Documents</li>
<li>Google Notebook</li>
<li>Picasa Web Albums</li>
<li>Spreadsheets</li>
<li>YouTube</li>
</ul>
<p>This tutorial will only deal with the Google Calendar service specifically, but it&#8217;s important to know that many of the techniques used here can easily be applied to other Google services.</p>
<p>The Google data Python Client Library requires Python 2.2 or greater and the ElementTree module to be installed. I recommend using Python 2.5 since the ElementTree module is included in that release of Python. This column assumes that you are using Python 2.5 and version 1.0.10 of the &#8220;gdata-python-client&#8221;.</p>
<h2>Getting and Installing  the &#8220;gdata-python-client&#8221;</h2>
<p>We must first download and install the &#8220;gdata-python-client&#8221; files from the &#8220;gdata-python-client&#8221; website.<a href="http://code.google.com/p/gdata-python-client/">[3]</a> Once you have downloaded the compressed file, extract it&#8217;s contents to a folder. You will then need to browse to that folder and run the extracted <code>setup.py</code> file with the <code>install</code> command with root access. For me, the command looked like this:</p>
<div class="hl-surround" style="height:28px;"><div class="hl-main"><pre><span class="hl-comment"># python2.5 setup.py install</span></pre></div></div>
<p>Notice that I ran <code>python2.5</code> instead of simply <code>python</code>. I did this to ensure that Python 2.5 was used instead of a previous version of Python.</p>
<p>Once you have done this, you can test to make sure that the <code>gdata-python-client</code> module has been installed properly by trying to import the <code>gdata</code> module. You can test this easily in the interactive Python shell:</p>
<div class="hl-surround" ><div class="hl-main"><pre><span class="hl-default">$ </span><span class="hl-identifier">python2</span><span class="hl-number">.5
</span><span class="hl-identifier">Python </span><span class="hl-number">2.5.2</span><span class="hl-identifier">a0 </span><span class="hl-brackets">(</span><span class="hl-identifier">r251</span><span class="hl-code">:</span><span class="hl-number">54863</span><span class="hl-code">, </span><span class="hl-identifier">Jan  </span><span class="hl-number">3 2008</span><span class="hl-code">, </span><span class="hl-number">17</span><span class="hl-code">:</span><span class="hl-number">59</span><span class="hl-code">:</span><span class="hl-number">56</span><span class="hl-brackets">)
[</span><span class="hl-identifier">GCC </span><span class="hl-number">4.2.3 20071123 </span><span class="hl-brackets">(</span><span class="hl-identifier">prerelease</span><span class="hl-brackets">) (</span><span class="hl-identifier">Debian </span><span class="hl-number">4.2.2</span><span class="hl-code">-</span><span class="hl-number">4</span><span class="hl-brackets">)] </span><span class="hl-identifier">on linux2
Type </span><span class="hl-quotes">&quot;</span><span class="hl-string">help</span><span class="hl-quotes">&quot;</span><span class="hl-default">, </span><span class="hl-quotes">&quot;</span><span class="hl-string">copyright</span><span class="hl-quotes">&quot;</span><span class="hl-default">, </span><span class="hl-quotes">&quot;</span><span class="hl-string">credits</span><span class="hl-quotes">&quot; </span><span class="hl-reserved">or </span><span class="hl-quotes">&quot;</span><span class="hl-string">license</span><span class="hl-quotes">&quot; </span><span class="hl-reserved">for </span><span class="hl-identifier">more information</span><span class="hl-default">.
&gt;&gt;&gt; </span><span class="hl-reserved">import </span><span class="hl-identifier">gdata</span><span class="hl-default">
&gt;&gt;&gt;</span></pre></div></div>
<p>If everything works properly you should see no errors when importing <code>gdata</code>. If you do run into problems, you can consult the <code>install.txt</code> file that was extracted with the rest of the files in the &#8220;gdata-python-client&#8221; archive that you downloaded.</p>
<h2>Getting Started</h2>
<p>There are some great Google Calendar examples that come with the &#8220;gdata-python-client&#8221; module. I found them to be very useful learning tools. The &#8220;Google Calendar Developers Guide&#8221;<a href="http://code.google.com/apis/calendar/developers_guide_python.html">[4]</a> is also very helpful. If you get stuck it is essential reading. The &#8220;Google Calendar API Reference Guide&#8221;<a href="http://code.google.com/apis/calendar/reference.html">[5]</a> is also an indispensable help.</p>
<p>It is important to remember that when you are working with the Google Calendar service, you are actually working with XML data. You are sending and receiving XML data to and from the Google Calendar service &#8211; Atom or RSS feeds to be precise. The Python classes that wrap these feeds, or XML blocks, are dynamically &#8220;formed&#8221; around the XML. When you access something like the following:</p>
<div class="hl-surround" style="height:28px;"><div class="hl-main"><pre><span class="hl-identifier">e_link</span><span class="hl-default">.</span><span class="hl-identifier">href</span></pre></div></div>
<p>You are actually accessing the &#8220;href&#8221; attribute of an XML link block that may look something like this:</p>
<div class="hl-surround" style="height:28px;"><div class="hl-main"><pre><span class="hl-brackets">&lt;</span><span class="hl-reserved">ns0 </span><span class="hl-var">:link href</span><span class="hl-code">=</span><span class="hl-quotes">&quot;</span><span class="hl-string">http://www.google.com/calendar/feeds/&lt;username&gt;/private/full</span><span class="hl-quotes">&quot; </span><span class="hl-var">rel</span><span class="hl-code">=</span><span class="hl-quotes">&quot;</span><span class="hl-string">alternate</span><span class="hl-quotes">&quot; </span><span class="hl-var">type</span><span class="hl-code">=</span><span class="hl-quotes">&quot;</span><span class="hl-string">application/atom+xml</span><span class="hl-quotes">&quot; </span><span class="hl-var">xmlns:ns0</span><span class="hl-code">=</span><span class="hl-quotes">&quot;</span><span class="hl-string">http:www.w3.org/2005/Atom</span><span class="hl-quotes">&quot; </span><span class="hl-brackets">/&gt;</span></pre></div></div>
<p>In the above example, if we had the link as an instance (perhaps an <code>atom.Link</code> object), <code>e_link.rel</code> would be equal to &#8220;alternate&#8221;.</p>
<h2>Logging In</h2>
<p>There are two types of Google calendars &#8211; public calendars and private calendars. Public calendars do not require any authentication while private calendars do. There are three forms of authentication for private calendars: &#8220;AuthSub proxy&#8221; authentication, &#8220;ClientLogin&#8221; authentication, and &#8220;Magic cookie&#8221; authentication.</p>
<p>&#8220;AuthSub proxy&#8221; authentication is meant for web applications so it will not be covered in this tutorial. &#8220;Magic cookie&#8221; authentication requires a string (the magic cookie) obtained from your Google Calendar settings page. This type of authentication gives you read only access to a private calendar. Its usage is quite specific and will not be covered in this column either.</p>
<p>For this column we will focus on good old-fashioned &#8220;ClientLogin&#8221; authentication. In order to perform &#8220;ClientLogin&#8221; authentication we need two things: a Google Calendar username and a password. If you do not have these, head over to the Google Calendar website <a href="http://www.google.com/calendar">[6]</a> and get yourself signed up. If you have gmail or have signed up for other Google services, you can probably sign in using that username and password.</p>
<p><strong>Note:</strong> I say username and so does the documentation, but this will actually be an email address.</p>
<p>We are going to read the username and password in from the command line using the <code>raw_input</code> function and the <code>getpass</code> module. I must thank the people who wrote the Google code examples for introducing me to the <code>getpass</code> module. Before looking through the examples, I had not heard of it.</p>
<p>The <code>raw_input</code> function simply reads a line of input from the command line and returns it with the newline stripped.  The <code>getpass.getpass</code> function does the exact same thing as <code>raw_input</code> except it does not echo the input, which is handy when working with passwords.</p>
<p>We need to import the <code>getpass</code> module:</p>
<div class="hl-surround" style="height:28px;"><div class="hl-main"><pre><span class="hl-reserved">import </span><span class="hl-identifier">getpass</span></pre></div></div>
<p>Then, in our <code>main</code> function we will ask the user to input their username and password:</p>
<div class="hl-surround" ><div class="hl-main"><pre><span class="hl-reserved">def </span><span class="hl-identifier">main</span><span class="hl-brackets">()</span><span class="hl-default">:
    </span><span class="hl-identifier">username</span><span class="hl-default"> = </span><span class="hl-builtin">raw_input</span><span class="hl-brackets">(</span><span class="hl-quotes">&quot;</span><span class="hl-string">Enter your username: </span><span class="hl-quotes">&quot;</span><span class="hl-brackets">)
    </span><span class="hl-identifier">password</span><span class="hl-default"> = </span><span class="hl-identifier">getpass</span><span class="hl-default">.</span><span class="hl-identifier">getpass</span><span class="hl-brackets">(</span><span class="hl-quotes">&quot;</span><span class="hl-string">Enter your password: </span><span class="hl-quotes">&quot;</span><span class="hl-brackets">)

</span><span class="hl-reserved">if </span><span class="hl-identifier">__name__</span><span class="hl-default"> == </span><span class="hl-quotes">&quot;</span><span class="hl-string">__main__</span><span class="hl-quotes">&quot;</span><span class="hl-default">:
    </span><span class="hl-identifier">main</span><span class="hl-brackets">()</span></pre></div></div>
<p>Now that we have our username and password, we need to log the user in. To do this we are going to use the <code>CalendarService</code> class. The <code>CalendarService</code> &#8220;extends the GDataService to streamline Google Calendar operations.&#8221; <a href="#7">[7]</a> The <code>GDataService</code> class &#8220;provides CRUD ops. and programmatic login for GData services.&#8221; <a href="#8">[8]</a>. CRUD is an acronym that stands for Create, Retrieve, Update, and Delete. What the <code>CalendarService</code> class will allow us to do is create, retrieve, update, and delete things from a Google Calendar.</p>
<p>The first step in logging in is to create an instance of the <code>CalendarService</code> class. To do this we will pass in the username and password that we have collected:</p>
<div class="hl-surround" ><div class="hl-main"><pre><span class="hl-identifier">calendar_service</span><span class="hl-default"> = </span><span class="hl-identifier">gdata</span><span class="hl-default">.</span><span class="hl-identifier">calendar</span><span class="hl-default">.</span><span class="hl-identifier">service</span><span class="hl-default">.</span><span class="hl-identifier">CalendarService</span><span class="hl-brackets">(</span><span class="hl-identifier">username</span><span class="hl-code">
    , </span><span class="hl-identifier">password</span><span class="hl-code">
    , </span><span class="hl-quotes">&quot;</span><span class="hl-string">PythonMagazine-Calendar_Example-1.0</span><span class="hl-quotes">&quot;</span><span class="hl-brackets">)</span></pre></div></div>
<p>The third parameter that we pass to the <code>CalendarService</code> constructor is the &#8220;source&#8221; string. This is a short &#8220;string identifying your application, for logging purposes. This string should take the form: &#8220;companyName-applicationName-versionID&#8221;"<a href="http://code.google.com/apis/accounts/AuthForInstalledApps.html">[9]</a></p>
<p>Now that we have a <code>CalendarService</code> instance, we need to login. To do this we will use the <code>ProgrammaticLogin</code> function. This will log into the Google Calendar using the <code>CalendarService</code> classes current username and password.  The <code>ProgrammaticLogin</code> function can raise three possible exceptions that we want to be aware of:</p>
<ol>
<li><strong>CaptchaRequired</strong> &#8211; Raised if the login requires a &#8220;captcha&#8221; response in order to login.</li>
<li><strong>BadAuthentication</strong> &#8211; Raised if the username and/or password were not accepted by the Google Calendar.</li>
<li><strong>Error</strong> &#8211; Raised if a 403 error occurs that is not a &#8220;CaptchaRequired&#8221; or &#8220;BadAuthentication&#8221; error.</li>
</ol>
<p>For this example, shown in Listing 1, we will only worry about the &#8220;BadAuthentication&#8221; exception.</p>
<p><strong>Listing 1</strong></p>
<div class="hl-surround" ><div class="hl-main"><pre><span class="hl-reserved">def </span><span class="hl-identifier">main</span><span class="hl-brackets">()</span><span class="hl-default">:
    </span><span class="hl-identifier">username</span><span class="hl-default"> = </span><span class="hl-builtin">raw_input</span><span class="hl-brackets">(</span><span class="hl-quotes">&quot;</span><span class="hl-string">Enter your username: </span><span class="hl-quotes">&quot;</span><span class="hl-brackets">)
    </span><span class="hl-identifier">password</span><span class="hl-default"> = </span><span class="hl-identifier">getpass</span><span class="hl-default">.</span><span class="hl-identifier">getpass</span><span class="hl-brackets">(</span><span class="hl-quotes">&quot;</span><span class="hl-string">Enter your password: </span><span class="hl-quotes">&quot;</span><span class="hl-brackets">)

    </span><span class="hl-identifier">calendar_service</span><span class="hl-default"> = </span><span class="hl-identifier">gdata</span><span class="hl-default">.</span><span class="hl-identifier">calendar</span><span class="hl-default">.</span><span class="hl-identifier">service</span><span class="hl-default">.</span><span class="hl-identifier">CalendarService</span><span class="hl-brackets">(</span><span class="hl-identifier">username</span><span class="hl-code">
        , </span><span class="hl-identifier">password</span><span class="hl-code">
        , </span><span class="hl-quotes">&quot;</span><span class="hl-string">PythonMagazine-Calendar_Example-1.0</span><span class="hl-quotes">&quot;</span><span class="hl-brackets">)
    </span><span class="hl-reserved">try</span><span class="hl-default">:
        </span><span class="hl-identifier">calendar_service</span><span class="hl-default">.</span><span class="hl-identifier">ProgrammaticLogin</span><span class="hl-brackets">()
    </span><span class="hl-reserved">except </span><span class="hl-identifier">gdata</span><span class="hl-default">.</span><span class="hl-identifier">service</span><span class="hl-default">.</span><span class="hl-identifier">BadAuthentication</span><span class="hl-default">, </span><span class="hl-identifier">e</span><span class="hl-default">:
        </span><span class="hl-reserved">print </span><span class="hl-quotes">&quot;</span><span class="hl-string">Authentication error logging in: %s</span><span class="hl-quotes">&quot;</span><span class="hl-default"> % </span><span class="hl-identifier">e
        </span><span class="hl-reserved">return
    except Exception</span><span class="hl-default">, </span><span class="hl-identifier">e</span><span class="hl-default">:
        </span><span class="hl-reserved">print </span><span class="hl-quotes">&quot;</span><span class="hl-string">Error Logging in: %s</span><span class="hl-quotes">&quot;</span><span class="hl-default"> % </span><span class="hl-identifier">e
        </span><span class="hl-reserved">return</span></pre></div></div>
<h2>Working With Calendars</h2>
<p>Now that we&#8217;ve logged into the calendar service, we can start working with the user&#8217;s available calendars. To get a list of all of the available calendars you can call the <code>GetAllCalendarsFeed</code> function. This will return a <code>CalendarListFeed</code> instance representing all of the user’s calendars. Since I want to show how to add and delete Calendars, I&#8217;m going to use the <code>GetOwnCalendarsFeed</code> function to get a list of all of the calendars that the &#8220;authenticated user has owner access to.&#8221;<a href="http://code.google.com/apis/calendar/developers_guide_python.html">[10]</a></p>
<p>The <code>GetOwnCalendarsFeed</code> function returns a <code>CalendarListFeed</code> class instance. This contains some information (like a title) along with a list of <code>CalendarListEntry</code> classes. Each <code>CalendarListEntry</code> in this list represents a calendar. An example of a function that uses <code>GetOwnCalendarsFeed</code> and then prints out information about each calendar can be found in Listing 2. Sample output from this function can be found in Listing 3. The function was passed a <code>CalendarService</code> after logging in:</p>
<div class="hl-surround" style="height:28px;"><div class="hl-main"><pre><span class="hl-identifier">list_own_calendars</span><span class="hl-brackets">(</span><span class="hl-identifier">calendar_service</span><span class="hl-brackets">)</span></pre></div></div>
<p><strong>Listing 2</strong></p>
<div class="hl-surround" style="height:280px;"><div class="hl-main"><pre><span class="hl-reserved">def </span><span class="hl-identifier">list_own_calendars</span><span class="hl-brackets">(</span><span class="hl-identifier">calendar_service</span><span class="hl-brackets">)</span><span class="hl-default">:

    </span><span class="hl-reserved">try</span><span class="hl-default">:
        </span><span class="hl-comment">#Get the CalendarListFeed
        </span><span class="hl-identifier">all_calendars_feed</span><span class="hl-default"> = </span><span class="hl-identifier">calendar_service</span><span class="hl-default">.</span><span class="hl-identifier">GetOwnCalendarsFeed</span><span class="hl-brackets">()
    </span><span class="hl-reserved">except Exception</span><span class="hl-default">, </span><span class="hl-identifier">e</span><span class="hl-default">:
        </span><span class="hl-reserved">print </span><span class="hl-quotes">&quot;</span><span class="hl-string">Error getting all calendar feed: %s</span><span class="hl-quotes">&quot;</span><span class="hl-default"> % </span><span class="hl-brackets">(</span><span class="hl-identifier">e</span><span class="hl-brackets">)
        </span><span class="hl-reserved">return
    </span><span class="hl-comment">#Print the feed's title
    </span><span class="hl-reserved">print </span><span class="hl-identifier">all_calendars_feed</span><span class="hl-default">.</span><span class="hl-identifier">title</span><span class="hl-default">.</span><span class="hl-identifier">text
    </span><span class="hl-comment">#Now loop through all of the CalendarListEntry items.
    </span><span class="hl-identifier">for </span><span class="hl-brackets">(</span><span class="hl-identifier">index</span><span class="hl-code">, </span><span class="hl-identifier">cal</span><span class="hl-brackets">) </span><span class="hl-reserved">in </span><span class="hl-builtin">enumerate</span><span class="hl-brackets">(</span><span class="hl-identifier">all_calendars_feed</span><span class="hl-code">.</span><span class="hl-identifier">entry</span><span class="hl-brackets">)</span><span class="hl-default">:
        </span><span class="hl-comment">#Print out the title and the summary if ther is one
        </span><span class="hl-identifier">if </span><span class="hl-brackets">(</span><span class="hl-identifier">cal</span><span class="hl-code">.</span><span class="hl-identifier">summary </span><span class="hl-reserved">is not None</span><span class="hl-brackets">)</span><span class="hl-default">:
            </span><span class="hl-reserved">print </span><span class="hl-quotes">&quot;</span><span class="hl-string">%d) %s - Summary: %s</span><span class="hl-quotes">&quot;</span><span class="hl-default"> % </span><span class="hl-brackets">(
                </span><span class="hl-identifier">index</span><span class="hl-code">, </span><span class="hl-identifier">cal</span><span class="hl-code">.</span><span class="hl-identifier">title</span><span class="hl-code">.</span><span class="hl-identifier">text</span><span class="hl-code">, </span><span class="hl-identifier">cal</span><span class="hl-code">.</span><span class="hl-identifier">summary</span><span class="hl-code">.</span><span class="hl-identifier">text</span><span class="hl-brackets">)
        </span><span class="hl-reserved">else</span><span class="hl-default">:
            </span><span class="hl-reserved">print </span><span class="hl-quotes">&quot;</span><span class="hl-string">%d) %s</span><span class="hl-quotes">&quot;</span><span class="hl-default"> % </span><span class="hl-brackets">(</span><span class="hl-identifier">index</span><span class="hl-code">, </span><span class="hl-identifier">cal</span><span class="hl-code">.</span><span class="hl-identifier">title</span><span class="hl-code">.</span><span class="hl-identifier">text</span><span class="hl-brackets">)
        </span><span class="hl-comment">#Print out the authors
        </span><span class="hl-reserved">print </span><span class="hl-quotes">&quot;</span><span class="hl-special">\t</span><span class="hl-string">Authors:</span><span class="hl-quotes">&quot;
        </span><span class="hl-reserved">for </span><span class="hl-identifier">author </span><span class="hl-reserved">in </span><span class="hl-identifier">cal</span><span class="hl-default">.</span><span class="hl-identifier">author</span><span class="hl-default">:
            </span><span class="hl-reserved">print </span><span class="hl-quotes">&quot;</span><span class="hl-special">\t\t</span><span class="hl-string">%s</span><span class="hl-quotes">&quot;</span><span class="hl-default"> % </span><span class="hl-brackets">(</span><span class="hl-identifier">author</span><span class="hl-code">.</span><span class="hl-identifier">name</span><span class="hl-code">.</span><span class="hl-identifier">text</span><span class="hl-brackets">)
        </span><span class="hl-comment">#Print out other information
        </span><span class="hl-reserved">print </span><span class="hl-quotes">&quot;</span><span class="hl-special">\t</span><span class="hl-string">Published: %s </span><span class="hl-special">\n\t</span><span class="hl-string">Updated: %s </span><span class="hl-special">\n\t</span><span class="hl-string">timezone: %s</span><span class="hl-quotes">&quot;</span><span class="hl-default"> % </span><span class="hl-brackets">(
            </span><span class="hl-identifier">cal</span><span class="hl-code">.</span><span class="hl-identifier">published</span><span class="hl-code">.</span><span class="hl-identifier">text</span><span class="hl-code">, </span><span class="hl-identifier">cal</span><span class="hl-code">.</span><span class="hl-identifier">updated</span><span class="hl-code">.</span><span class="hl-identifier">text</span><span class="hl-code">, </span><span class="hl-identifier">cal</span><span class="hl-code">.</span><span class="hl-identifier">timezone</span><span class="hl-code">.</span><span class="hl-identifier">value</span><span class="hl-brackets">)
        </span><span class="hl-reserved">print </span><span class="hl-quotes">&quot;</span><span class="hl-special">\t</span><span class="hl-string">Colour: %s </span><span class="hl-special">\n\t</span><span class="hl-string">Hidden: %s </span><span class="hl-special">\n\t</span><span class="hl-string">Selected: %s</span><span class="hl-quotes">&quot;</span><span class="hl-default"> % </span><span class="hl-brackets">(
            </span><span class="hl-identifier">cal</span><span class="hl-code">.</span><span class="hl-identifier">color</span><span class="hl-code">.</span><span class="hl-identifier">value</span><span class="hl-code">, </span><span class="hl-identifier">cal</span><span class="hl-code">.</span><span class="hl-identifier">hidden</span><span class="hl-code">.</span><span class="hl-identifier">value</span><span class="hl-code">, </span><span class="hl-identifier">cal</span><span class="hl-code">.</span><span class="hl-identifier">selected</span><span class="hl-code">.</span><span class="hl-identifier">value</span><span class="hl-brackets">)
        </span><span class="hl-reserved">print </span><span class="hl-quotes">&quot;</span><span class="hl-special">\t</span><span class="hl-string">Access Level: %s</span><span class="hl-quotes">&quot;</span><span class="hl-default"> % </span><span class="hl-brackets">(</span><span class="hl-identifier">cal</span><span class="hl-code">.</span><span class="hl-identifier">access_level</span><span class="hl-code">.</span><span class="hl-identifier">value</span><span class="hl-brackets">)</span></pre></div></div>
<p><strong>Listing 3</strong></p>
<div class="hl-surround" style="height:280px;"><div class="hl-main"><pre>Mark Mruss's Calendar List
0) Mark Mruss - Summary: Main Calendar
	Authors:
		Mark Mruss
	Published: 2008-02-07T04:15:15.701Z
	Updated: 2008-02-07T03:43:26.000Z
	timezone: America/Toronto
	Colour: #5229A3
	Hidden: false
	Selected: true
	Access Level: owner
1) PythonMagazine - Summary: Calendar for Articles
	Authors:
		PythonMagazine
	Published: 2008-02-07T04:15:15.702Z
	Updated: 2008-02-07T03:37:15.000Z
	timezone: America/Toronto
	Colour: #0D7813
	Hidden: false
	Selected: true
	Access Level: owner</pre></div></div>
<h2>Adding a Calendar</h2>
<p>If we want to add a calendar, we need to create a <code>CalendarListEntry</code> class instance and then call the <code>CalendarService</code> classes <code>InsertCalendar</code> function. Let&#8217;s say I wanted to add a Banking calendar to my account, I could do the following to create the <code>CalendarListEntry</code>:</p>
<div class="hl-surround" ><div class="hl-main"><pre><span class="hl-identifier">new_calendar</span><span class="hl-default"> = </span><span class="hl-identifier">gdata</span><span class="hl-default">.</span><span class="hl-identifier">calendar</span><span class="hl-default">.</span><span class="hl-identifier">CalendarListEntry</span><span class="hl-brackets">()
</span><span class="hl-identifier">new_calendar</span><span class="hl-default">.</span><span class="hl-identifier">title</span><span class="hl-default"> = </span><span class="hl-identifier">gdata</span><span class="hl-default">.</span><span class="hl-identifier">atom</span><span class="hl-default">.</span><span class="hl-identifier">Title</span><span class="hl-brackets">(</span><span class="hl-identifier">text</span><span class="hl-code">=</span><span class="hl-quotes">&quot;</span><span class="hl-string">Banking</span><span class="hl-quotes">&quot;</span><span class="hl-brackets">)
</span><span class="hl-identifier">new_calendar</span><span class="hl-default">.</span><span class="hl-identifier">summary</span><span class="hl-default"> = </span><span class="hl-identifier">gdata</span><span class="hl-default">.</span><span class="hl-identifier">atom</span><span class="hl-default">.</span><span class="hl-identifier">Summary</span><span class="hl-brackets">(</span><span class="hl-identifier">text</span><span class="hl-code">=</span><span class="hl-quotes">&quot;</span><span class="hl-string">Bills and payments</span><span class="hl-quotes">&quot;</span><span class="hl-brackets">)
</span><span class="hl-identifier">new_calendar</span><span class="hl-default">.</span><span class="hl-identifier">timezone</span><span class="hl-default"> = </span><span class="hl-identifier">gdata</span><span class="hl-default">.</span><span class="hl-identifier">calendar</span><span class="hl-default">.</span><span class="hl-identifier">Timezone</span><span class="hl-brackets">(</span><span class="hl-identifier">value</span><span class="hl-code">=</span><span class="hl-quotes">&quot;</span><span class="hl-string">America/Toronto</span><span class="hl-quotes">&quot;</span><span class="hl-brackets">)
</span><span class="hl-identifier">new_calendar</span><span class="hl-default">.</span><span class="hl-identifier">hidden</span><span class="hl-default"> = </span><span class="hl-identifier">gdata</span><span class="hl-default">.</span><span class="hl-identifier">calendar</span><span class="hl-default">.</span><span class="hl-identifier">Hidden</span><span class="hl-brackets">(</span><span class="hl-identifier">value</span><span class="hl-code">=</span><span class="hl-quotes">&quot;</span><span class="hl-string">false</span><span class="hl-quotes">&quot;</span><span class="hl-brackets">)
</span><span class="hl-identifier">new_calendar</span><span class="hl-default">.</span><span class="hl-identifier">selected</span><span class="hl-default"> = </span><span class="hl-identifier">gdata</span><span class="hl-default">.</span><span class="hl-identifier">calendar</span><span class="hl-default">.</span><span class="hl-identifier">Selected</span><span class="hl-brackets">(</span><span class="hl-identifier">value</span><span class="hl-code">=</span><span class="hl-quotes">&quot;</span><span class="hl-string">true</span><span class="hl-quotes">&quot;</span><span class="hl-brackets">)</span></pre></div></div>
<p>The calendar now needs to be added to the account:</p>
<div class="hl-surround" ><div class="hl-main"><pre><span class="hl-reserved">try</span><span class="hl-default">:
    </span><span class="hl-identifier">created_calendar</span><span class="hl-default"> = </span><span class="hl-identifier">calendar_service</span><span class="hl-default">.</span><span class="hl-identifier">InsertCalendar</span><span class="hl-brackets">(</span><span class="hl-identifier">new_calendar</span><span class="hl-brackets">)
</span><span class="hl-reserved">except </span><span class="hl-identifier">gdata</span><span class="hl-default">.</span><span class="hl-identifier">service</span><span class="hl-default">.</span><span class="hl-identifier">RequestError</span><span class="hl-default">, </span><span class="hl-identifier">e</span><span class="hl-default">:
    </span><span class="hl-reserved">print </span><span class="hl-quotes">&quot;</span><span class="hl-string">Error adding calendar: %s</span><span class="hl-quotes">&quot;</span><span class="hl-default"> % </span><span class="hl-brackets">(</span><span class="hl-identifier">e</span><span class="hl-brackets">[</span><span class="hl-number">0</span><span class="hl-brackets">][</span><span class="hl-quotes">&quot;</span><span class="hl-string">reason</span><span class="hl-quotes">&quot;</span><span class="hl-brackets">])</span></pre></div></div>
<p>This will add the new calendar to the authenticated users list of calendars, make it visible, and select it. Notice that <code>InsertCalendar</code> also returns a <code>CalendarListEntry</code> instance. This is the calendar that was actually added to the authenticated user’s list of calendars. It is wrapping the XML that represents the actual calendar, as opposed to the smaller version that we created for insertion.</p>
<h2>Deleting a Calendar</h2>
<p>Deleting a Calendar is very easy. You simply need to call the <code>CalendarService</code> classes <code>DeleteCalendarEntry</code> function. The <code>DeleteCalendarEntry</code> function takes three parameters which are documented in the source code:</p>
<ol>
<li><strong>edit_uri</strong> &#8211; The edit uri (Uniform Resource Identifier) of the Calendar that you want to delete.</li>
<li><strong>url_params</strong> &#8211; Defaults to None. A dictionary containing URL parameters that will be included in the delete.</li>
<li><strong>escape_params</strong> &#8211; Defaults to True. A boolean that controls whether or not the <code>url_params</code> will be escaped.</li>
</ol>
<p><strong>Note</strong>: There is another optional parameter: <code>extra_headers</code>, which is the second parameter, but at this point it does not seem to be used at all in the source code.</p>
<p>The simplest case is to ignore the optional parameters and simply pass in the edit uri of the calendar that you wish to delete. You can get the edit uri of a calendar by calling the <code>GetEditLink</code> function of the <code>CalendarListEntry</code> instance that represents the calendar that you are going to delete. An example of a function that will delete a calendar can be seen in Listing 4. This function takes a <code>CalendarService</code> instance and a <code>CalendarListEntry</code> instance as parameters.</p>
<p><strong>Listing 4</strong></p>
<div class="hl-surround" ><div class="hl-main"><pre><span class="hl-reserved">def </span><span class="hl-identifier">delete_calendar</span><span class="hl-brackets">(</span><span class="hl-identifier">calendar_service</span><span class="hl-code">, </span><span class="hl-identifier">calendar</span><span class="hl-brackets">)</span><span class="hl-default">:
    </span><span class="hl-identifier">e_link</span><span class="hl-default"> = </span><span class="hl-identifier">calendar</span><span class="hl-default">.</span><span class="hl-identifier">GetEditLink</span><span class="hl-brackets">()
    </span><span class="hl-identifier">if </span><span class="hl-brackets">(</span><span class="hl-identifier">e_link </span><span class="hl-reserved">is not None</span><span class="hl-brackets">)</span><span class="hl-default">:
        </span><span class="hl-reserved">try</span><span class="hl-default">:
            </span><span class="hl-identifier">calendar_service</span><span class="hl-default">.</span><span class="hl-identifier">DeleteCalendarEntry</span><span class="hl-brackets">(</span><span class="hl-identifier">e_link</span><span class="hl-code">.</span><span class="hl-identifier">href</span><span class="hl-brackets">)
        </span><span class="hl-reserved">except </span><span class="hl-identifier">gdata</span><span class="hl-default">.</span><span class="hl-identifier">service</span><span class="hl-default">.</span><span class="hl-identifier">RequestError</span><span class="hl-default">, </span><span class="hl-identifier">e</span><span class="hl-default">:
            </span><span class="hl-reserved">print </span><span class="hl-quotes">&quot;</span><span class="hl-string">Error deleting calendar: %s</span><span class="hl-quotes">&quot;</span><span class="hl-default"> % </span><span class="hl-brackets">(</span><span class="hl-identifier">e</span><span class="hl-brackets">[</span><span class="hl-number">0</span><span class="hl-brackets">][</span><span class="hl-quotes">&quot;</span><span class="hl-string">reason</span><span class="hl-quotes">&quot;</span><span class="hl-brackets">])</span></pre></div></div>
<h2>Listing Events</h2>
<p>Now let’s take a look at events. Events are items that are added to a specific calendar. If you want to remind yourself to pay your bills at the end of the month you might add that to your banking calendar. That &#8220;note&#8221; on your calendar is an event.</p>
<p>You can get a list of events for the primary calendar using the <code>CalendarService</code> classes <code>GetCalendarEventFeed</code> function. Since you may be working with more than one calendar, it&#8217;s probably more useful to be able to list the events for a specific calendar. You can do this in one of two ways:</p>
<ol>
<li>You can pass in the optional <code>uri</code> parameter to the <code>GetCalendarEventFeed</code> function.  From testing I found that a Calendar&#8217;s &#8220;alternate&#8221; link works.</li>
<li>You can use the  <code>CalendarService</code> classes <code>CalendarQuery</code> function to query for a specific calendars event feed.</li>
</ol>
<p>If you want to use the first option you can use the <code>CalendarListEntry</code> classes <code>GetAlternateLink</code> member function to get the uri, and then pass it to <code>GetCalendarEventFeed</code>:</p>
<div class="hl-surround" ><div class="hl-main"><pre><span class="hl-identifier">a_link</span><span class="hl-default"> = </span><span class="hl-identifier">calendar</span><span class="hl-default">.</span><span class="hl-identifier">GetAlternateLink</span><span class="hl-brackets">()
</span><span class="hl-comment">#Make sure the link is valid
</span><span class="hl-identifier">if </span><span class="hl-brackets">(</span><span class="hl-identifier">a_link </span><span class="hl-reserved">is not None</span><span class="hl-brackets">)</span><span class="hl-default">:
    </span><span class="hl-identifier">event_feed</span><span class="hl-default"> = </span><span class="hl-identifier">calendar_service</span><span class="hl-default">.</span><span class="hl-identifier">GetCalendarEventFeed</span><span class="hl-brackets">(</span><span class="hl-identifier">a_link</span><span class="hl-code">.</span><span class="hl-identifier">href</span><span class="hl-brackets">)</span></pre></div></div>
<p>If you use the <code>CalendarQuery</code> method, you need to get the calendar username (or id) of the calendar whose events you want to query. It seems strange to me that there appears to be no way to get a calendar&#8217;s username besides parsing one of the calendar&#8217;s links. The username of a calendar can be found in the alternate link after &#8220;feeds&#8221; and before the visibility and projection:</p>
<div class="hl-surround" style="height:28px;"><div class="hl-main"><pre><span class="hl-default">http://www.google.com/calendar/feeds/</span><span class="hl-brackets">&lt;</span><span class="hl-code"> &lt;</span><span class="hl-reserved">username</span><span class="hl-brackets">&gt;</span><span class="hl-default">&gt;/private/full</span></pre></div></div>
<p>Note: You can use the username &#8220;default&#8221; to query the default calendar.</p>
<p>For the sake of simplicity I will use the alternate link method for my examples. A full example that prints out calendar data and a calendar&#8217;s events can be found in Listing 5. The method that prints out the event data is called <code>print_event_feed</code>. It is called near the end of the <code>list_own_calendars</code> method:</p>
<div class="hl-surround" ><div class="hl-main"><pre><span class="hl-comment"># Now Print out the events
</span><span class="hl-reserved">print </span><span class="hl-quotes">&quot;</span><span class="hl-string">Events:</span><span class="hl-quotes">&quot;
</span><span class="hl-identifier">a_link</span><span class="hl-default"> = </span><span class="hl-identifier">cal</span><span class="hl-default">.</span><span class="hl-identifier">GetAlternateLink</span><span class="hl-brackets">()
</span><span class="hl-identifier">if </span><span class="hl-brackets">(</span><span class="hl-identifier">a_link </span><span class="hl-reserved">is not None</span><span class="hl-brackets">)</span><span class="hl-default">:
    </span><span class="hl-identifier">event_feed</span><span class="hl-default"> = </span><span class="hl-identifier">calendar_service</span><span class="hl-default">.</span><span class="hl-identifier">GetCalendarEventFeed</span><span class="hl-brackets">(</span><span class="hl-identifier">a_link</span><span class="hl-code">.</span><span class="hl-identifier">href</span><span class="hl-brackets">)
    </span><span class="hl-identifier">print_event_feed</span><span class="hl-brackets">(</span><span class="hl-identifier">event_feed</span><span class="hl-brackets">)</span></pre></div></div>
<p><strong>Listing 5</strong></p>
<div class="hl-surround" style="height:280px;"><div class="hl-main"><pre><span class="hl-comment">#! /usr/bin/env python

</span><span class="hl-reserved">import </span><span class="hl-identifier">gdata</span><span class="hl-default">.</span><span class="hl-identifier">calendar</span><span class="hl-default">.</span><span class="hl-identifier">service
</span><span class="hl-reserved">import </span><span class="hl-identifier">getpass

</span><span class="hl-reserved">def </span><span class="hl-identifier">print_event_feed</span><span class="hl-brackets">(</span><span class="hl-identifier">event_feed</span><span class="hl-brackets">)</span><span class="hl-default">:

    </span><span class="hl-reserved">for </span><span class="hl-identifier">index</span><span class="hl-default">, </span><span class="hl-identifier">event </span><span class="hl-reserved">in </span><span class="hl-builtin">enumerate</span><span class="hl-brackets">(</span><span class="hl-identifier">event_feed</span><span class="hl-code">.</span><span class="hl-identifier">entry</span><span class="hl-brackets">)</span><span class="hl-default">:
        </span><span class="hl-reserved">print </span><span class="hl-quotes">&quot;</span><span class="hl-special">\t</span><span class="hl-string">%d) %s</span><span class="hl-special">\r\n\t</span><span class="hl-string">Content: %s</span><span class="hl-quotes">&quot;</span><span class="hl-default"> % </span><span class="hl-brackets">(
                </span><span class="hl-identifier">index</span><span class="hl-code">, </span><span class="hl-identifier">event</span><span class="hl-code">.</span><span class="hl-identifier">title</span><span class="hl-code">.</span><span class="hl-identifier">text</span><span class="hl-code">, </span><span class="hl-identifier">event</span><span class="hl-code">.</span><span class="hl-identifier">content</span><span class="hl-code">.</span><span class="hl-identifier">text</span><span class="hl-brackets">)
        </span><span class="hl-reserved">print </span><span class="hl-quotes">&quot;</span><span class="hl-special">\t\t</span><span class="hl-string">Who:</span><span class="hl-quotes">&quot;
        </span><span class="hl-reserved">for </span><span class="hl-identifier">person </span><span class="hl-reserved">in </span><span class="hl-identifier">event</span><span class="hl-default">.</span><span class="hl-identifier">who</span><span class="hl-default">:
            </span><span class="hl-reserved">print </span><span class="hl-quotes">&quot;</span><span class="hl-special">\t\t\t</span><span class="hl-string">Name: %s</span><span class="hl-special">\n\t\t\t</span><span class="hl-string">email: %s</span><span class="hl-quotes">&quot;</span><span class="hl-default"> % </span><span class="hl-brackets">(</span><span class="hl-identifier">person</span><span class="hl-code">.</span><span class="hl-identifier">name</span><span class="hl-code">
                , </span><span class="hl-identifier">person</span><span class="hl-code">.</span><span class="hl-identifier">email</span><span class="hl-brackets">)
        </span><span class="hl-reserved">print </span><span class="hl-quotes">&quot;</span><span class="hl-special">\t\t</span><span class="hl-string">Authors:</span><span class="hl-quotes">&quot;
        </span><span class="hl-reserved">for </span><span class="hl-identifier">author </span><span class="hl-reserved">in </span><span class="hl-identifier">event</span><span class="hl-default">.</span><span class="hl-identifier">author</span><span class="hl-default">:
            </span><span class="hl-reserved">print </span><span class="hl-quotes">&quot;</span><span class="hl-special">\t\t\t</span><span class="hl-string">%s</span><span class="hl-quotes">&quot;</span><span class="hl-default"> % </span><span class="hl-brackets">(</span><span class="hl-identifier">author</span><span class="hl-code">.</span><span class="hl-identifier">name</span><span class="hl-code">.</span><span class="hl-identifier">text</span><span class="hl-brackets">)
        </span><span class="hl-reserved">print </span><span class="hl-quotes">&quot;</span><span class="hl-special">\t\t</span><span class="hl-string">When:</span><span class="hl-quotes">&quot;
        </span><span class="hl-reserved">for </span><span class="hl-identifier">e_index</span><span class="hl-default">, </span><span class="hl-identifier">e_time </span><span class="hl-reserved">in </span><span class="hl-builtin">enumerate</span><span class="hl-brackets">(</span><span class="hl-identifier">event</span><span class="hl-code">.</span><span class="hl-identifier">when</span><span class="hl-brackets">)</span><span class="hl-default">:
            </span><span class="hl-reserved">print </span><span class="hl-quotes">&quot;</span><span class="hl-special">\t\t\t</span><span class="hl-string">%d) Start time: %s</span><span class="hl-special">\n\t\t\t</span><span class="hl-string">End time: %s</span><span class="hl-quotes">&quot;</span><span class="hl-default"> % </span><span class="hl-brackets">(
                </span><span class="hl-identifier">e_index</span><span class="hl-code">
                , </span><span class="hl-identifier">e_time</span><span class="hl-code">.</span><span class="hl-identifier">start_time</span><span class="hl-code">
                , </span><span class="hl-identifier">e_time</span><span class="hl-code">.</span><span class="hl-identifier">end_time</span><span class="hl-brackets">)

</span><span class="hl-reserved">def </span><span class="hl-identifier">list_own_calendars</span><span class="hl-brackets">(</span><span class="hl-identifier">calendar_service</span><span class="hl-brackets">)</span><span class="hl-default">:

    </span><span class="hl-reserved">try</span><span class="hl-default">:
        </span><span class="hl-comment">#Get the CalendarListFeed
        </span><span class="hl-identifier">all_calendars_feed</span><span class="hl-default"> = </span><span class="hl-identifier">calendar_service</span><span class="hl-default">.</span><span class="hl-identifier">GetOwnCalendarsFeed</span><span class="hl-brackets">()
    </span><span class="hl-reserved">except Exception</span><span class="hl-default">, </span><span class="hl-identifier">e</span><span class="hl-default">:
        </span><span class="hl-reserved">print </span><span class="hl-quotes">&quot;</span><span class="hl-string">Error getting all calendar feed: %s</span><span class="hl-quotes">&quot;</span><span class="hl-default"> % </span><span class="hl-brackets">(</span><span class="hl-identifier">e</span><span class="hl-brackets">)
        </span><span class="hl-reserved">return
    </span><span class="hl-comment">#Print the feed's title
    </span><span class="hl-reserved">print </span><span class="hl-identifier">all_calendars_feed</span><span class="hl-default">.</span><span class="hl-identifier">title</span><span class="hl-default">.</span><span class="hl-identifier">text
    </span><span class="hl-comment">#Now loop through all of the CalendarListEntry items.
    </span><span class="hl-identifier">for </span><span class="hl-brackets">(</span><span class="hl-identifier">index</span><span class="hl-code">, </span><span class="hl-identifier">cal</span><span class="hl-brackets">) </span><span class="hl-reserved">in </span><span class="hl-builtin">enumerate</span><span class="hl-brackets">(</span><span class="hl-identifier">all_calendars_feed</span><span class="hl-code">.</span><span class="hl-identifier">entry</span><span class="hl-brackets">)</span><span class="hl-default">:
        </span><span class="hl-comment">#Print out the title and the summary if there is one
        </span><span class="hl-identifier">if </span><span class="hl-brackets">(</span><span class="hl-identifier">cal</span><span class="hl-code">.</span><span class="hl-identifier">summary </span><span class="hl-reserved">is not None</span><span class="hl-brackets">)</span><span class="hl-default">:
            </span><span class="hl-reserved">print </span><span class="hl-quotes">&quot;</span><span class="hl-string">%d) %s - Summary: %s</span><span class="hl-quotes">&quot;</span><span class="hl-default"> % </span><span class="hl-brackets">(
                </span><span class="hl-identifier">index</span><span class="hl-code">, </span><span class="hl-identifier">cal</span><span class="hl-code">.</span><span class="hl-identifier">title</span><span class="hl-code">.</span><span class="hl-identifier">text</span><span class="hl-code">, </span><span class="hl-identifier">cal</span><span class="hl-code">.</span><span class="hl-identifier">summary</span><span class="hl-code">.</span><span class="hl-identifier">text</span><span class="hl-brackets">)
        </span><span class="hl-reserved">else</span><span class="hl-default">:
            </span><span class="hl-reserved">print </span><span class="hl-quotes">&quot;</span><span class="hl-string">%d) %s</span><span class="hl-quotes">&quot;</span><span class="hl-default"> % </span><span class="hl-brackets">(</span><span class="hl-identifier">index</span><span class="hl-code">, </span><span class="hl-identifier">cal</span><span class="hl-code">.</span><span class="hl-identifier">title</span><span class="hl-code">.</span><span class="hl-identifier">text</span><span class="hl-brackets">)
        </span><span class="hl-comment">#Print out the authors
        </span><span class="hl-reserved">print </span><span class="hl-quotes">&quot;</span><span class="hl-special">\t</span><span class="hl-string">Authors:</span><span class="hl-quotes">&quot;
        </span><span class="hl-reserved">for </span><span class="hl-identifier">author </span><span class="hl-reserved">in </span><span class="hl-identifier">cal</span><span class="hl-default">.</span><span class="hl-identifier">author</span><span class="hl-default">:
            </span><span class="hl-reserved">print </span><span class="hl-quotes">&quot;</span><span class="hl-special">\t\t</span><span class="hl-string">%s</span><span class="hl-quotes">&quot;</span><span class="hl-default"> % </span><span class="hl-brackets">(</span><span class="hl-identifier">author</span><span class="hl-code">.</span><span class="hl-identifier">name</span><span class="hl-code">.</span><span class="hl-identifier">text</span><span class="hl-brackets">)
        </span><span class="hl-comment">#Print out other information
        </span><span class="hl-reserved">print </span><span class="hl-quotes">&quot;</span><span class="hl-special">\t</span><span class="hl-string">Published: %s </span><span class="hl-special">\n\t</span><span class="hl-string">Updated: %s </span><span class="hl-special">\n\t</span><span class="hl-string">timezone: %s</span><span class="hl-quotes">&quot;</span><span class="hl-default"> % </span><span class="hl-brackets">(
            </span><span class="hl-identifier">cal</span><span class="hl-code">.</span><span class="hl-identifier">published</span><span class="hl-code">.</span><span class="hl-identifier">text</span><span class="hl-code">, </span><span class="hl-identifier">cal</span><span class="hl-code">.</span><span class="hl-identifier">updated</span><span class="hl-code">.</span><span class="hl-identifier">text</span><span class="hl-code">, </span><span class="hl-identifier">cal</span><span class="hl-code">.</span><span class="hl-identifier">timezone</span><span class="hl-code">.</span><span class="hl-identifier">value</span><span class="hl-brackets">)
        </span><span class="hl-reserved">print </span><span class="hl-quotes">&quot;</span><span class="hl-special">\t</span><span class="hl-string">Colour: %s </span><span class="hl-special">\n\t</span><span class="hl-string">Hidden: %s </span><span class="hl-special">\n\t</span><span class="hl-string">Selected: %s</span><span class="hl-quotes">&quot;</span><span class="hl-default"> % </span><span class="hl-brackets">(
            </span><span class="hl-identifier">cal</span><span class="hl-code">.</span><span class="hl-identifier">color</span><span class="hl-code">.</span><span class="hl-identifier">value</span><span class="hl-code">, </span><span class="hl-identifier">cal</span><span class="hl-code">.</span><span class="hl-identifier">hidden</span><span class="hl-code">.</span><span class="hl-identifier">value</span><span class="hl-code">, </span><span class="hl-identifier">cal</span><span class="hl-code">.</span><span class="hl-identifier">selected</span><span class="hl-code">.</span><span class="hl-identifier">value</span><span class="hl-brackets">)
        </span><span class="hl-reserved">print </span><span class="hl-quotes">&quot;</span><span class="hl-special">\t</span><span class="hl-string">Access Level: %s</span><span class="hl-quotes">&quot;</span><span class="hl-default"> % </span><span class="hl-brackets">(</span><span class="hl-identifier">cal</span><span class="hl-code">.</span><span class="hl-identifier">access_level</span><span class="hl-code">.</span><span class="hl-identifier">value</span><span class="hl-brackets">)
        </span><span class="hl-comment"># Now Print out the events
        </span><span class="hl-reserved">print </span><span class="hl-quotes">&quot;</span><span class="hl-special">\t</span><span class="hl-string">Events:</span><span class="hl-quotes">&quot;
        </span><span class="hl-identifier">a_link</span><span class="hl-default"> = </span><span class="hl-identifier">cal</span><span class="hl-default">.</span><span class="hl-identifier">GetAlternateLink</span><span class="hl-brackets">()
        </span><span class="hl-identifier">if </span><span class="hl-brackets">(</span><span class="hl-identifier">a_link </span><span class="hl-reserved">is not None</span><span class="hl-brackets">)</span><span class="hl-default">:
            </span><span class="hl-identifier">event_feed</span><span class="hl-default"> = </span><span class="hl-identifier">calendar_service</span><span class="hl-default">.</span><span class="hl-identifier">GetCalendarEventFeed</span><span class="hl-brackets">(</span><span class="hl-identifier">a_link</span><span class="hl-code">.</span><span class="hl-identifier">href</span><span class="hl-brackets">)
            </span><span class="hl-identifier">print_event_feed</span><span class="hl-brackets">(</span><span class="hl-identifier">event_feed</span><span class="hl-brackets">)

</span><span class="hl-reserved">def </span><span class="hl-identifier">main</span><span class="hl-brackets">()</span><span class="hl-default">:
    </span><span class="hl-identifier">username</span><span class="hl-default"> = </span><span class="hl-builtin">raw_input</span><span class="hl-brackets">(</span><span class="hl-quotes">&quot;</span><span class="hl-string">Enter your username: </span><span class="hl-quotes">&quot;</span><span class="hl-brackets">)
    </span><span class="hl-identifier">password</span><span class="hl-default"> = </span><span class="hl-identifier">getpass</span><span class="hl-default">.</span><span class="hl-identifier">getpass</span><span class="hl-brackets">(</span><span class="hl-quotes">&quot;</span><span class="hl-string">Enter your password: </span><span class="hl-quotes">&quot;</span><span class="hl-brackets">)

    </span><span class="hl-identifier">calendar_service</span><span class="hl-default"> = </span><span class="hl-identifier">gdata</span><span class="hl-default">.</span><span class="hl-identifier">calendar</span><span class="hl-default">.</span><span class="hl-identifier">service</span><span class="hl-default">.</span><span class="hl-identifier">CalendarService</span><span class="hl-brackets">(</span><span class="hl-identifier">username</span><span class="hl-code">
        , </span><span class="hl-identifier">password</span><span class="hl-code">
        , </span><span class="hl-quotes">&quot;</span><span class="hl-string">PythonMagazine-Calendar_Example-1.0</span><span class="hl-quotes">&quot;</span><span class="hl-brackets">)
    </span><span class="hl-reserved">try</span><span class="hl-default">:
        </span><span class="hl-identifier">calendar_service</span><span class="hl-default">.</span><span class="hl-identifier">ProgrammaticLogin</span><span class="hl-brackets">()
    </span><span class="hl-reserved">except </span><span class="hl-identifier">gdata</span><span class="hl-default">.</span><span class="hl-identifier">service</span><span class="hl-default">.</span><span class="hl-identifier">BadAuthentication</span><span class="hl-default">, </span><span class="hl-identifier">e</span><span class="hl-default">:
        </span><span class="hl-reserved">print </span><span class="hl-quotes">&quot;</span><span class="hl-string">Authentication error logging in: %s</span><span class="hl-quotes">&quot;</span><span class="hl-default"> % </span><span class="hl-identifier">e
        </span><span class="hl-reserved">return
    except Exception</span><span class="hl-default">, </span><span class="hl-identifier">e</span><span class="hl-default">:
        </span><span class="hl-reserved">print </span><span class="hl-quotes">&quot;</span><span class="hl-string">Error Logging in: %s</span><span class="hl-quotes">&quot;</span><span class="hl-default"> % </span><span class="hl-identifier">e
        </span><span class="hl-reserved">return

    </span><span class="hl-identifier">list_own_calendars</span><span class="hl-brackets">(</span><span class="hl-identifier">calendar_service</span><span class="hl-brackets">)

</span><span class="hl-reserved">if </span><span class="hl-identifier">__name__</span><span class="hl-default"> == </span><span class="hl-quotes">&quot;</span><span class="hl-string">__main__</span><span class="hl-quotes">&quot;</span><span class="hl-default">:
    </span><span class="hl-identifier">main</span><span class="hl-brackets">()</span></pre></div></div>
<p>An example of the output produced by Listing 5 can be seen in Listing 6. Don&#8217;t mind the formatting &#8211; it&#8217;s not pretty. It&#8217;s merely meant to give you an example of some of the data that you can mine from an event feed.</p>
<p><strong>Listing 6</strong></p>
<div class="hl-surround" style="height:280px;"><div class="hl-main"><pre>Mark Mruss's Calendar List
0) Mark Mruss - Summary: Main Calendar
	Authors:
		Mark Mruss
	Published: 2008-02-12T02:30:18.731Z
	Updated: 2008-02-08T04:03:10.000Z
	timezone: America/Toronto
	Colour: #5229A3
	Hidden: false
	Selected: true
	Access Level: owner
	Events:
	0) Dinner at the Drake
	Content: Dinner
		Who:
			Name: Mark Mruss
			email: mark.mruss@gmail.com
		Authors:
			Mark Mruss
		When:
			0) Start time: 2008-02-15T21:00:00.000-05:00
			End time: 2008-02-15T22:30:00.000-05:00
	1) Cezanne's Closet
	Content: Cezanne's Closet
		Who:
			Name: Mark Mruss
			email: mark.mruss@gmail.com
		Authors:
			Mark Mruss
		When:
			0) Start time: 2008-02-09
			End time: 2008-02-11</pre></div></div>
<h2>Adding an Event</h2>
<p>Adding a new event to a calendar is very similar to creating a new calendar. You need to create a new <code>CalendarEventEntry</code> instance. You then populate it with options, and pass it to the <code>CalendarService</code> classes <code>InsertEvent</code> function, along with the alternate link of the calendar to which you would like to add the event.</p>
<p>If you take a look at Listing 7 you can see a simple example of how to add an all day event. If you want to specify an event that lasts for less then a day, or include a specific start and end time, you need to use the &#8220;RFC 3339 timestamp&#8221; format for your <code>start_time</code> and <code>end_time</code> values. Also notice that just like adding a Calendar, the newly created event is returned by the <code>InsertEvent</code> function.</p>
<p><strong>Listing 7</strong></p>
<div class="hl-surround" ><div class="hl-main"><pre><span class="hl-identifier">a_link</span><span class="hl-default"> = </span><span class="hl-identifier">calendar</span><span class="hl-default">.</span><span class="hl-identifier">GetAlternateLink</span><span class="hl-brackets">()
</span><span class="hl-identifier">if </span><span class="hl-brackets">(</span><span class="hl-identifier">a_link </span><span class="hl-reserved">is not None</span><span class="hl-brackets">)</span><span class="hl-default">:

    </span><span class="hl-identifier">new_event</span><span class="hl-default"> = </span><span class="hl-identifier">gdata</span><span class="hl-default">.</span><span class="hl-identifier">calendar</span><span class="hl-default">.</span><span class="hl-identifier">CalendarEventEntry</span><span class="hl-brackets">()
    </span><span class="hl-identifier">new_event</span><span class="hl-default">.</span><span class="hl-identifier">title</span><span class="hl-default"> = </span><span class="hl-identifier">gdata</span><span class="hl-default">.</span><span class="hl-identifier">atom</span><span class="hl-default">.</span><span class="hl-identifier">Title</span><span class="hl-brackets">(</span><span class="hl-identifier">text</span><span class="hl-code">=</span><span class="hl-quotes">&quot;</span><span class="hl-string">New Article</span><span class="hl-quotes">&quot;</span><span class="hl-brackets">)
    </span><span class="hl-identifier">new_event</span><span class="hl-default">.</span><span class="hl-identifier">content</span><span class="hl-default"> = </span><span class="hl-identifier">gdata</span><span class="hl-default">.</span><span class="hl-identifier">atom</span><span class="hl-default">.</span><span class="hl-identifier">Content</span><span class="hl-brackets">(</span><span class="hl-identifier">text</span><span class="hl-code">=</span><span class="hl-quotes">&quot;</span><span class="hl-string">Write Article</span><span class="hl-quotes">&quot;</span><span class="hl-brackets">)
    </span><span class="hl-identifier">new_event</span><span class="hl-default">.</span><span class="hl-identifier">when</span><span class="hl-default">.</span><span class="hl-identifier">append</span><span class="hl-brackets">(</span><span class="hl-identifier">gdata</span><span class="hl-code">.</span><span class="hl-identifier">calendar</span><span class="hl-code">.</span><span class="hl-identifier">When</span><span class="hl-brackets">(
        </span><span class="hl-identifier">start_time</span><span class="hl-code">=</span><span class="hl-quotes">&quot;</span><span class="hl-string">2008-02-20</span><span class="hl-quotes">&quot;</span><span class="hl-code">
        , </span><span class="hl-identifier">end_time</span><span class="hl-code">=</span><span class="hl-quotes">&quot;</span><span class="hl-string">2008-02-21</span><span class="hl-quotes">&quot;</span><span class="hl-brackets">))
    </span><span class="hl-reserved">try</span><span class="hl-default">:
        </span><span class="hl-identifier">created_event</span><span class="hl-default"> = </span><span class="hl-identifier">calendar_service</span><span class="hl-default">.</span><span class="hl-identifier">InsertEvent</span><span class="hl-brackets">(</span><span class="hl-identifier">new_event</span><span class="hl-code">
            , </span><span class="hl-identifier">a_link</span><span class="hl-code">.</span><span class="hl-identifier">href</span><span class="hl-brackets">)
    </span><span class="hl-reserved">except </span><span class="hl-identifier">gdata</span><span class="hl-default">.</span><span class="hl-identifier">service</span><span class="hl-default">.</span><span class="hl-identifier">RequestError</span><span class="hl-default">, </span><span class="hl-identifier">e</span><span class="hl-default">:
        </span><span class="hl-reserved">print </span><span class="hl-quotes">&quot;</span><span class="hl-string">Error adding event: %s</span><span class="hl-quotes">&quot;</span><span class="hl-default"> % </span><span class="hl-brackets">(</span><span class="hl-identifier">e</span><span class="hl-brackets">[</span><span class="hl-number">0</span><span class="hl-brackets">][</span><span class="hl-quotes">&quot;</span><span class="hl-string">reason</span><span class="hl-quotes">&quot;</span><span class="hl-brackets">])</span></pre></div></div>
<h2>Deleting an Event</h2>
<p>Deleting an event is (you guessed it) almost identical to deleting an entire calendar. This is because both helper functions wrap the same <code>GDataService</code> base class function. However the <code>'DeleteEvent</code> event function does a little bit more work than the <code>DeleteCalendarEntry</code> function by making sure that your <code>edit_uri</code> is in the correct format.</p>
<p>To delete an event you simply need to call the <code>DeleteEvent</code> function of the <code>CalendarService</code> class. An example of a function that will delete an event can be seen in Listing 8. This function takes a <code>CalendarService</code> instance and a <code>CalendarEventEntry</code> instance as parameters. As with the majority of these actions, the <code>CalendarService</code> instance should already be authenticated.</p>
<p><strong>Listing 8</strong></p>
<div class="hl-surround" ><div class="hl-main"><pre><span class="hl-reserved">def </span><span class="hl-identifier">delete_event</span><span class="hl-brackets">(</span><span class="hl-identifier">calendar_service</span><span class="hl-code">, </span><span class="hl-identifier">event</span><span class="hl-brackets">)</span><span class="hl-default">:
    </span><span class="hl-identifier">e_link</span><span class="hl-default"> = </span><span class="hl-identifier">event</span><span class="hl-default">.</span><span class="hl-identifier">GetEditLink</span><span class="hl-brackets">()
    </span><span class="hl-identifier">if </span><span class="hl-brackets">(</span><span class="hl-identifier">e_link </span><span class="hl-reserved">is not None</span><span class="hl-brackets">)</span><span class="hl-default">:
        </span><span class="hl-reserved">try</span><span class="hl-default">:
            </span><span class="hl-identifier">calendar_service</span><span class="hl-default">.</span><span class="hl-identifier">DeleteEvent</span><span class="hl-brackets">(</span><span class="hl-identifier">e_link</span><span class="hl-code">.</span><span class="hl-identifier">href</span><span class="hl-brackets">)
        </span><span class="hl-reserved">except </span><span class="hl-identifier">gdata</span><span class="hl-default">.</span><span class="hl-identifier">service</span><span class="hl-default">.</span><span class="hl-identifier">RequestError</span><span class="hl-default">, </span><span class="hl-identifier">e</span><span class="hl-default">:
            </span><span class="hl-reserved">print </span><span class="hl-quotes">&quot;</span><span class="hl-string">Error deleting event: %s</span><span class="hl-quotes">&quot;</span><span class="hl-default"> % </span><span class="hl-brackets">(</span><span class="hl-identifier">e</span><span class="hl-brackets">[</span><span class="hl-number">0</span><span class="hl-brackets">][</span><span class="hl-quotes">&quot;</span><span class="hl-string">reason</span><span class="hl-quotes">&quot;</span><span class="hl-brackets">])</span></pre></div></div>
<h2>Conclusion</h2>
<p>Hopefully this article has given you a small taste of what is possible with the <code>gdata-python-client</code> module and Google Calendars. Maybe you can already imagine a use for these features in your next Python application? Please keep in mind that there is much more that can be done with Google Calendars, including updating existing Calendars and Events (<code>CalendarService</code> member functions: <code>UpdateCalendar</code> and <code>UpdateEvent</code>), and almost any other task you can perform using the &#8220;online&#8221; version of the Google Calendar service.</p>
<p>Also, it is important to note that the Python documentation for the Google Calendar service is sparse but growing. A lot of what is contained in this article was found through browsing the examples, the <code>gdata-python-client</code> source code, other people&#8217;s examples, as well as a whole bunch of trial and error on my part. Since this is the case, there may be other ways, or more preferred methods of accomplishing what I have shown here.</p>
<p><a href="http://code.google.com/p/gdata-python-client/">[1] http://code.google.com/p/gdata-python-client/</a><br />
<a href="http://code.google.com/apis/gdata/index.html">[2] http://code.google.com/apis/gdata/index.html</a><br />
<a href="http://code.google.com/p/gdata-python-client/">[3] http://code.google.com/p/gdata-python-client/</a><br />
<a href="http://code.google.com/apis/calendar/developers_guide_python.html">[4] http://code.google.com/apis/calendar/developers_guide_python.html</a><br />
<a href="http://code.google.com/apis/calendar/reference.html">[5] http://code.google.com/apis/calendar/reference.html</a><br />
<a href="http://www.google.com/calendar">[6] http://www.google.com/calendar</a><br />
<a name="7">[7] gdata.calendar.service.py (From the source comments)</a><br />
<a name="8">[8] gdata.service.py (From the source comments)</a><br />
<a href="http://code.google.com/apis/accounts/AuthForInstalledApps.html">[9] http://code.google.com/apis/accounts/AuthForInstalledApps.html</a><br />
<a href="http://code.google.com/apis/calendar/developers_guide_python.html">[10] http://code.google.com/apis/calendar/developers_guide_python.html</a><br />
</ns0></p>
<div style="float:right;margin:0px 0px 0px 0px;"><a href="http://www.google.com/reader/link?url=http://www.learningpython.com/2010/02/27/an-introduction-to-google-calendars/&title=An Introduction to Google Calendars&srcTitle=learning python&srcURL=http://www.learningpython.com"target="_blank" rel=""><img border="0" src="http://www.learningpython.com/wp-content/plugins/wp-google-buzz/icon/12.png" style="opacity:1;filter:alpha(opacity=100)" onmouseover="this.style.opacity=0.8;this.filters.alpha.opacity=70" onmouseout="this.style.opacity=1;this.filters.alpha.opacity=100"/> </a></div>]]></content:encoded>
			<wfw:commentRss>http://www.learningpython.com/2010/02/27/an-introduction-to-google-calendars/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Introducing Docstrings</title>
		<link>http://www.learningpython.com/2010/01/08/introducing-docstrings/</link>
		<comments>http://www.learningpython.com/2010/01/08/introducing-docstrings/#comments</comments>
		<pubDate>Sat, 09 Jan 2010 03:41:06 +0000</pubDate>
		<dc:creator>selsine</dc:creator>
				<category><![CDATA[Python Magazine]]></category>
		<category><![CDATA[python]]></category>
		<category><![CDATA[docstrings]]></category>
		<category><![CDATA[PythonMagazine]]></category>

		<guid isPermaLink="false">http://www.learningpython.com/?p=118</guid>
		<description><![CDATA[
			
				
			
		
By: Mark Mruss
Note: This article was first published the February 2008 issue of Python Magazine
Of all the tasks assigned to programmers, commenting code and writing documentation are among the most disliked.  This article introduces you to Python&#8217;s documentation strings. While they won&#8217;t make commenting your code any more enjoyable, they will provide a systematic [...]]]></description>
			<content:encoded><![CDATA[<div class="tweetmeme_button" style="float: right; margin-left: 10px;">
			<a href="http://api.tweetmeme.com/share?url=http%3A%2F%2Fwww.learningpython.com%2F2010%2F01%2F08%2Fintroducing-docstrings%2F"><br />
				<img src="http://api.tweetmeme.com/imagebutton.gif?url=http%3A%2F%2Fwww.learningpython.com%2F2010%2F01%2F08%2Fintroducing-docstrings%2F&amp;style=normal" height="61" width="50" /><br />
			</a>
		</div>
<p><strong>By: Mark Mruss</strong></p>
<p><strong>Note:</strong> This article was first published the <a href="http://www.pythonmagazine.com/c/issue/view/66">February 2008 issue</a> of <a href="http://www.pythonmagazine.com">Python Magazine</a></p>
<p>Of all the tasks assigned to programmers, commenting code and writing documentation are among the most disliked.  This article introduces you to Python&#8217;s documentation strings. While they won&#8217;t make commenting your code any more enjoyable, they will provide a systematic approach to doing it, as well as access to additional tools for documentation generation and testing.</p>
<p></p>
<p><span id="more-118"></span></p>
<p>You&#8217;ve just finished your new Python module. You can&#8217;t wait to upload it to the Web and let all the other Python hackers start using it. The only step left is the most dreaded for many programmers: documentation. Unless you&#8217;ve been commenting and documenting your code as you wrote it, you&#8217;re going to have to go back through each source file, class, and function, trying to remember exactly what your code was supposed to do. Not an enjoyable task.</p>
<p>Sound familiar to you? If it does, you&#8217;re probably not using documentation strings, commonly known as doc strings or docstrings (I prefer docstrings, without the space), or any of the handy tools that work with docstrings. This article will introduce you to Python&#8217;s docstrings, and a few of the tools that make them a great addition to your code.</p>
<h2>Docstrings</h2>
<p>If you are not already using docstrings in your Python code, you really should. They provide a standard way to comment your code, giving you and other developers (who might want to use your code at some point) easy access to descriptions of the modules, classes, and functions found within.</p>
<p>At the heart of it, docstrings are simply comments placed in special locations in your Python source code. These comments can then be looked at by tools designed to work with docstrings or other Python programmers using your code. Note that I said using// your code, not reading your code. This is because docstrings are accessible via a Python object&#8217;s <code>__doc__</code> attribute. This is very helpful is you are testing out a new module in Python&#8217;s interactive shell and really need to know what sort of parameters a certain function needs.</p>
<p>Pep 257 has a good definition of docstrings: &#8220;A docstring is a string literal that occurs as the first statement in a module, function, class, or method definition. Such a docstring becomes the __doc__ special attribute of that object.&#8221;<a href="#1">[1]</a>  Definitions are nice but it might be easier to look at a quick example of some docstrings:</p>
<div class="hl-surround" ><div class="hl-main"><pre>def add(x, y):
    &quot;&quot;&quot;This is the add function's docstring.&quot;&quot;&quot;
	return x + y</pre></div></div>
<div class="hl-surround" ><div class="hl-main"><pre>def subtract(x, y):
    &quot;&quot;&quot;This is the subtract function's docstring.
    It is longer then the add functions, it goes
    on and on and on and on.&quot;&quot;&quot;
    return x - y</pre></div></div>
<p>Since docstrings are comments they can be in any format that you want, however since this is Python there are a few style guidelines that you should probably be aware of. You don&#8217;t have to follow these guidlines but if you do it will be easier for other Python programmers to understand and work with your code.</p>
<p>In general there are two types of docstrings: one-line docstrings and multi-line docstrings. The difference between the two should be fairly obvious: one-line docstrings are only one line in length and multi-line docstrings are more then one line in length. One-line docstrings and multi-line docstrings each have different style guidelines that will be explained in more detail in the following two sections.</p>
<h2>One-Line Docstrings</h2>
<p>Let&#8217;s look at a quick example of a one-line docstring for a simple function:</p>
<div class="hl-surround" ><div class="hl-main"><pre>def add(x, y):
    &quot;&quot;&quot;Return the sum of two numbers.&quot;&quot;&quot;
    return x + y</pre></div></div>
<p>In this example <code>"""Return the sum of two numbers."""</code> is the docstring of the <code>add</code> function. If you were to run the following:</p>
<div class="hl-surround" style="height:28px;"><div class="hl-main"><pre>print add.__doc__</pre></div></div>
<p>The output would look like this:</p>
<div class="hl-surround" style="height:28px;"><div class="hl-main"><pre>Return the sum of two numbers.</pre></div></div>
<p>In his &#8220;Python Style Guide&#8221; Guido van Rossum has a few notes on the preferred style of one line docstrings:</p>
<ul>
<li>Triple quotes are used even though the string fits on one line. This makes it easy to later expand it.</li>
<li>The closing quotes are on the same line as the opening quotes. This looks better for one-liners.</li>
<li>There&#8217;s no blank line either before or after the doc string.</li>
<li>The doc string is a phrase ending in a period. It prescribes the function&#8217;s effect as a command (&#8221;<strong>Do</strong> this&#8221;, &#8220;<strong>Return</strong> that&#8221;), not as a description: e.g. don&#8217;t write &#8220;Returns the pathname &#8230;&#8221; <a href="#2">[2]</a></li>
</ul>
<p>One-line docstrings should only be used to document the simplest of cases. If what you are documenting does anything complicated, accepts input, or returns a value, it&#8217;s probably a good idea to use a multi-line docstring.</p>
<h2>Multi-Line Docstrings</h2>
<p>Multi-line docstrings should be used to document the majority of your modules, classes, functions, and methods. This is because most of what you are programming performs tasks more complicated then that which can fit into a single sentence summary. Multi-line docstrings should be used to documents the input, output, and complex behaviour of your objects. Like one-line docstrings, multi-line docstrings should start with a single sentence summary. After that there should be a blank line and then a more detailed description. The blank line separating the one line summary and the additional information is important as certain tools will use the blank line to separate the summary from the rest of the docstring. An example of a multi-line comment can be found in Listing 1.</p>
<p><strong>Listing 1</strong></p>
<div class="hl-surround" ><div class="hl-main"><pre><span class="hl-reserved">def </span><span class="hl-identifier">subtract</span><span class="hl-brackets">(</span><span class="hl-identifier">x</span><span class="hl-code">, </span><span class="hl-identifier">y</span><span class="hl-brackets">)</span><span class="hl-default">:
    </span><span class="hl-quotes">&quot;&quot;&quot;</span><span class="hl-string">Return the difference between two numbers.

    Arguments:
    x -- The minuend.
    y -- The subtrahend.

    Returns:
    A number, the difference between x and y (ie. x - y)

    </span><span class="hl-quotes">&quot;&quot;&quot;
    </span><span class="hl-reserved">return </span><span class="hl-identifier">x</span><span class="hl-default"> - </span><span class="hl-identifier">y</span></pre></div></div>
<h2>What to Document</h2>
<p>There are also style guidelines that dictate what you should include in your multi-line docstrings when documenting different sections of your code. These are general guidelines but following them will help ensure that your code is well documented and easily understood by other Python programmers. For more information on this please see Guido&#8217;s &#8220;Python Style Guide&#8221;.<a href="#2">[2]</a></p>
<p><strong>Modules</strong> &#8211; Document the module and provide a one line summary of everything that is exported by the module. (eg. classes, exceptions, and functions).</p>
<p><strong>Classes</strong> &#8211; Summarize the functionality of the class. List all public methods and data members of the class. If there is any addition information needed to subclass the class, or if there is an additional interface for subclasses provide a description.</p>
<p><strong>Functions and Methods</strong> &#8211; Summarize the functionality of the function and &#8220;document its arguments, return value(s), side effects, exceptions raised, and restrictions on when it can be called (all if applicable).&#8221;<a href="#3">[3]</a></p>
<p>An example of all of these can be found in Listing 2.</p>
<p><strong>Listing 2</strong></p>
<div class="hl-surround" style="height:280px;"><div class="hl-main"><pre><span class="hl-comment">#!/usr/bin/env python
</span><span class="hl-quotes">&quot;&quot;&quot;</span><span class="hl-string">A simple math module.

Exported Classes:

Math -- A simple math class with mathematical functions.

</span><span class="hl-quotes">&quot;&quot;&quot;

</span><span class="hl-reserved">class </span><span class="hl-identifier">Math</span><span class="hl-brackets">(</span><span class="hl-identifier">object</span><span class="hl-brackets">)</span><span class="hl-default">:
    </span><span class="hl-quotes">&quot;&quot;&quot;</span><span class="hl-string">A simple math class with mathematical functions.

    Public functions:
    add -- Adds two numbers together and
    returns the result.

    subtract -- Returns the difference between
    two numbers.

    </span><span class="hl-quotes">&quot;&quot;&quot;

    </span><span class="hl-reserved">def </span><span class="hl-identifier">subtract</span><span class="hl-brackets">(</span><span class="hl-identifier">self</span><span class="hl-code">, </span><span class="hl-identifier">x</span><span class="hl-code">, </span><span class="hl-identifier">y</span><span class="hl-brackets">)</span><span class="hl-default">:
        </span><span class="hl-quotes">&quot;&quot;&quot;</span><span class="hl-string">Return the difference between two numbers.

        Arguments:
        x -- The minuend.
        y -- The subtrahend.

        Returns:
        A number, the difference between x and y (ie. x - y)

        </span><span class="hl-quotes">&quot;&quot;&quot;
        </span><span class="hl-reserved">return </span><span class="hl-identifier">x</span><span class="hl-default"> - </span><span class="hl-identifier">y

    </span><span class="hl-reserved">def </span><span class="hl-identifier">add</span><span class="hl-brackets">(</span><span class="hl-identifier">self</span><span class="hl-code">, </span><span class="hl-identifier">x</span><span class="hl-code">, </span><span class="hl-identifier">y</span><span class="hl-brackets">)</span><span class="hl-default">:
        </span><span class="hl-quotes">&quot;&quot;&quot;</span><span class="hl-string">Return the sum of two numbers.

        Arguments:
        x -- Number to be summed.
        y -- Number to be summed.

        Returns:
        A number, the sum of x and y (ie. x + y)

        </span><span class="hl-quotes">&quot;&quot;&quot;
        </span><span class="hl-reserved">return </span><span class="hl-identifier">x</span><span class="hl-default"> + </span><span class="hl-identifier">y</span></pre></div></div>
<h2>Documentation Generation</h2>
<p>Generally if you have a complicated module or API people would rather read a help file, or online documentation, as opposed to constantly having find and browse the source code. Thankfully for us there are many different documentation generation tools out there that make use of docstrings. So when you are writing your docstrings, you aren&#8217;t just commenting your source code you&#8217;re also writing your help file!</p>
<p>The easiest tool to use is PyDoc, it&#8217;s a module, and a stand-alone application, that has been included in the Python standard library since version 2.1. There is much that can be done with PyDoc but for this column we are going to focus on it&#8217;s documentation generation. PyDoc can take the docstrings found within a module and output them as either simple text documentation (much like UNIX or Linux man pages) or HTML documentation.</p>
<p>Creating HTML documentation of the <code>SimpleMath</code> module used in Listing 2 is very easy. On a UNIX like computer (Linux, OS X, etc.) it can be accomplished using the following command:</p>
<div class="hl-surround" style="height:28px;"><div class="hl-main"><pre>$ pydoc -w /home/selsine/python/SimpleMath.py</pre></div></div>
<p>On Windows the command will look something like this:</p>
<div class="hl-surround" style="height:28px;"><div class="hl-main"><pre>C:&gt;c:Python25Libpydoc.py -w c:pythonSimpleMath.py</pre></div></div>
<p>This will create an HTML file named <code>SimpleMath.html</code> in the current folder. A sample of what the generated HTML looks like can be seen in Figure 1. </p>
<div id="attachment_124" class="wp-caption alignnone" style="width: 462px"><img src="http://www.learningpython.com/wp-content/uploads/2010/01/firgure1.png" alt="Figure 1 - pydoc" title="Figure 1 - pydoc" width="452" height="538" class="size-full wp-image-124" /><p class="wp-caption-text">Figure 1 - pydoc</p></div>
<p>While PyDoc is a great tool and easy to use because it is in the standard library, there are a few other tools out there that you might consider using. If you look at the HTML file that PyDoc generates you will notice that it does not mark up your docstrings. It simply reads them from your source code and spits them back out. If you are looking for something a little bit fancier with a few more options you might consider Epydoc<a href="#4">[4]</a> or docutils<a href="#5">[5]</a>.</p>
<p>Both Epydoc and docutils use simple markup languages to give the documentation generated a bit more punch. Docutils uses the reStructuredText markup language. While Epydoc uses the Epytext markup language, as well as being able to work with Javadoc and reStructuredText. An example of the HTML that Epydoc produces can be seen in Figure 2. The code that was used to generate the HTML can be found in Listing 3.</p>
<p><img src="http://www.learningpython.com/wp-content/uploads/2010/01/firgure2.png" alt="Figure 2 - Epydoc" title="Figure 2 - Epydoc" class="alignnone size-full wp-image-125" /><br />
Figure 2 &#8211; Epydoc</p>
<p><strong>Listing 3</strong></p>
<div class="hl-surround" style="height:280px;"><div class="hl-main"><pre><span class="hl-comment">#!/usr/bin/env python
</span><span class="hl-quotes">&quot;&quot;&quot;</span><span class="hl-string">A simple math module.

Exported Classes:

Math -- A simple math class with mathematical functions.

</span><span class="hl-quotes">&quot;&quot;&quot;

</span><span class="hl-reserved">class </span><span class="hl-identifier">Math</span><span class="hl-brackets">(</span><span class="hl-identifier">object</span><span class="hl-brackets">)</span><span class="hl-default">:
    </span><span class="hl-quotes">&quot;&quot;&quot;</span><span class="hl-string">A simple math class with mathematical functions.

    Public functions:
    add -- Adds two numbers together and
    returns the result.

    subtract -- Returns the difference between
    two numbers.

    </span><span class="hl-quotes">&quot;&quot;&quot;

    </span><span class="hl-reserved">def </span><span class="hl-identifier">subtract</span><span class="hl-brackets">(</span><span class="hl-identifier">self</span><span class="hl-code">, </span><span class="hl-identifier">x</span><span class="hl-code">, </span><span class="hl-identifier">y</span><span class="hl-brackets">)</span><span class="hl-default">:
        </span><span class="hl-quotes">&quot;&quot;&quot;</span><span class="hl-string">Return the difference between two numbers.

        @type   x: number
        @param  x: The minuend.
        @type   y: number
        @param  y: The subtrahend.

        @rtype: number
        @returns: A number, the difference between x and y (ie. x - y)

        </span><span class="hl-quotes">&quot;&quot;&quot;
        </span><span class="hl-reserved">return </span><span class="hl-identifier">x</span><span class="hl-default"> - </span><span class="hl-identifier">y

    </span><span class="hl-reserved">def </span><span class="hl-identifier">add</span><span class="hl-brackets">(</span><span class="hl-identifier">self</span><span class="hl-code">, </span><span class="hl-identifier">x</span><span class="hl-code">, </span><span class="hl-identifier">y</span><span class="hl-brackets">)</span><span class="hl-default">:
        </span><span class="hl-quotes">&quot;&quot;&quot;</span><span class="hl-string">Return the sum of two numbers.

        @type   x: number
        @param  x: Number to be summed.
        @type   y: number
        @param  y: Number to be summed.

        @rtype: number
        @returns: A number, the sum of x and y (ie. x + y)

        </span><span class="hl-quotes">&quot;&quot;&quot;
        </span><span class="hl-reserved">return </span><span class="hl-identifier">x</span><span class="hl-default"> + </span><span class="hl-identifier">y

</span><span class="hl-reserved">def </span><span class="hl-identifier">_test</span><span class="hl-brackets">()</span><span class="hl-default">:
    </span><span class="hl-reserved">import </span><span class="hl-identifier">doctest
    doctest</span><span class="hl-default">.</span><span class="hl-identifier">testmod</span><span class="hl-brackets">()

</span><span class="hl-reserved">if </span><span class="hl-identifier">__name__</span><span class="hl-default"> == </span><span class="hl-quotes">&quot;</span><span class="hl-string">__main__</span><span class="hl-quotes">&quot;</span><span class="hl-default">:
    </span><span class="hl-identifier">_test</span><span class="hl-brackets">()</span></pre></div></div>
<h2>Doctest</h2>
<p>One of the most interesting uses of docstrings is unit testing using the <code>doctest</code> module. As we all know testing our code is important, and (as many of us have begun to learn) writing unit tests for large projects is a great way to ensure that changes in one area of a project don&#8217;t cause problems elsewhere in the code. If you don&#8217;t know what a unit test is it&#8217;s basically a simple test case to prove whether a specific area of your code is functioning properly. Generally at least one unit test is created for each object in order to test the correctness of the project as a whole.</p>
<p>In a nutshell the the doctest<code> module searches your dostrings "for pieces of text that look like interactive Python sessions, and then executes those sessions to verify that they work exactly as shown."<a href="#6">[6]</a> This means that it will search your docstrings for lines that start with </code><code>>>></code> or with <code>...</code> if they are the continuation of a statement (i.e. the inside of a function).  If there is output generated by the statements it &#8220;must immediately follow the final &#8216;>>> &#8216; or &#8216;&#8230; &#8216; line containing the code, and &#8230; extends to the next &#8216;>>> &#8216; or all-whitespace line.&#8221;<a href="#7">[7]</a> Adding doctests doesn&#8217;t just add unit tests to your code it also provides working examples in your docstrings and documentation.</p>
<p>Since doctests are formatted to look like interactive Python sessions a simple way to write them is to use Python&#8217;s interactive shell. You do this by simply executing your code in the interactive shell, and then copying and pasting the resulting test into your docstrings. For example, if we were to use this method to write a doctest for our subtract method we could do something like the following in the interactive shell:</p>
<div class="hl-surround" ><div class="hl-main"><pre>&gt;&gt;&gt; from SimpleMath import Math
&gt;&gt;&gt; simple_math = Math()
&gt;&gt;&gt; simple_math.subtract(10, 7)
3
&gt;&gt;&gt;</pre></div></div>
<p>We don&#8217;t need to import our module for the doctest so all we will need to copy from the interactive shell are the middle three lines:</p>
<div class="hl-surround" ><div class="hl-main"><pre>&gt;&gt;&gt; simple_math = Math()
&gt;&gt;&gt; simple_math.subtract(10, 7)
3</pre></div></div>
<p>As you can see, what we have here is a test compromising of two lines of Python code and then the expected result. The <code>SimpleMath</code> module containing a doctest for each function can be found in Listing 4.</p>
<p><strong>Listing 4</strong></p>
<div class="hl-surround" style="height:280px;"><div class="hl-main"><pre><span class="hl-comment">#!/usr/bin/env python
</span><span class="hl-quotes">&quot;&quot;&quot;</span><span class="hl-string">A simple math module.

Exported Classes:

Math -- A simple math class with mathematical functions.

</span><span class="hl-quotes">&quot;&quot;&quot;

</span><span class="hl-reserved">class </span><span class="hl-identifier">Math</span><span class="hl-brackets">(</span><span class="hl-identifier">object</span><span class="hl-brackets">)</span><span class="hl-default">:
    </span><span class="hl-quotes">&quot;&quot;&quot;</span><span class="hl-string">A simple math class with mathematical functions.

    Public functions:
    add -- Adds two numbers together and
    returns the result.

    subtract -- Returns the difference between
    two numbers.

    </span><span class="hl-quotes">&quot;&quot;&quot;

    </span><span class="hl-reserved">def </span><span class="hl-identifier">subtract</span><span class="hl-brackets">(</span><span class="hl-identifier">self</span><span class="hl-code">, </span><span class="hl-identifier">x</span><span class="hl-code">, </span><span class="hl-identifier">y</span><span class="hl-brackets">)</span><span class="hl-default">:
        </span><span class="hl-quotes">&quot;&quot;&quot;</span><span class="hl-string">Return the difference between two numbers.

        &gt;&gt;&gt; simple_math = Math()
        &gt;&gt;&gt; simple_math.subtract(10, 7)
        3

        @type   x: number
        @param  x: The minuend.
        @type   y: number
        @param  y: The subtrahend.

        @rtype: number
        @returns: A number, the difference between x and y (ie. x - y)

        </span><span class="hl-quotes">&quot;&quot;&quot;
        </span><span class="hl-reserved">return </span><span class="hl-identifier">x</span><span class="hl-default"> - </span><span class="hl-identifier">y

    </span><span class="hl-reserved">def </span><span class="hl-identifier">add</span><span class="hl-brackets">(</span><span class="hl-identifier">self</span><span class="hl-code">, </span><span class="hl-identifier">x</span><span class="hl-code">, </span><span class="hl-identifier">y</span><span class="hl-brackets">)</span><span class="hl-default">:
        </span><span class="hl-quotes">&quot;&quot;&quot;</span><span class="hl-string">Return the sum of two numbers.

        &gt;&gt;&gt; simple_math = Math()
        &gt;&gt;&gt; simple_math.add(10, 7)
        17

        @type   x: number
        @param  x: Number to be summed.
        @type   y: number
        @param  y: Number to be summed.

        @rtype: number
        @returns: A number, the sum of x and y (ie. x + y)

        </span><span class="hl-quotes">&quot;&quot;&quot;
        </span><span class="hl-reserved">return </span><span class="hl-identifier">x</span><span class="hl-default"> + </span><span class="hl-identifier">y

</span><span class="hl-reserved">def </span><span class="hl-identifier">_test</span><span class="hl-brackets">()</span><span class="hl-default">:
    </span><span class="hl-reserved">import </span><span class="hl-identifier">doctest
    doctest</span><span class="hl-default">.</span><span class="hl-identifier">testmod</span><span class="hl-brackets">()

</span><span class="hl-reserved">if </span><span class="hl-identifier">__name__</span><span class="hl-default"> == </span><span class="hl-quotes">&quot;</span><span class="hl-string">__main__</span><span class="hl-quotes">&quot;</span><span class="hl-default">:
    </span><span class="hl-identifier">_test</span><span class="hl-brackets">()</span></pre></div></div>
<p>If you look at Listing 4 you will also notice the following code at the end of the source:</p>
<div class="hl-surround" ><div class="hl-main"><pre>def _test():
    import doctest
    doctest.testmod()

if __name__ == &quot;__main__&quot;:
    _test()</pre></div></div>
<p>This is the code that will be executed if the module is launched directly from the command line. The code will import the <code>doctest</code> module and then use the <code>testmod</code> method to test the current module. Now when we run our <code>SimpleMath.py</code> file directly we will get the following:</p>
<div class="hl-surround" ><div class="hl-main"><pre>$ python SimpleMath.py
$</pre></div></div>
<p>Since nothing was written out to the command line we know that all of the doctests were successful. If you want to get more information you can use the -v<code> flag to produce verbose output:</p>
<div class="hl-surround" style="height:28px;"><div class="hl-main"><pre>$ python SimpleMath.py -v</pre></div></div>
<p>If you were to encounter an error it would look something like Listing 5.</p>
<p><strong>Listing 5</strong></p>
<div class="hl-surround" ><div class="hl-main"><pre>**********************************************************************
File &quot;SimpleMath.py&quot;, line 26, in __main__.Math.subtract
Failed example:
    simple_math.subtract(10, 7)
Expected:
    4
Got:
    3
**********************************************************************
1 items had failures:
   1 of   2 in __main__.Math.subtract
***Test Failed*** 1 failures.</pre></div></div>
<p>As an added bonus if you are using Epydoc or docutils to generate your documentation, both tools will recognize doctest sections and highlight them. An example of what it looks like when Epydoc does this can be seen in Figure 3.</p>
<div id="attachment_129" class="wp-caption alignnone" style="width: 310px"><img src="http://www.learningpython.com/wp-content/uploads/2010/01/firgure3-300x115.png" alt="Figure 3 - doctest" title="Figure 3 - doctest" width="300" height="115" class="size-medium wp-image-129" /><p class="wp-caption-text">Figure 3 - doctest</p></div>
<h2>Conclusion</h2>
<p>Hopefully by this point you can see how useful docstrings can be to any Python code that you write. They give you a structured way to document your source code, the ability to easily generate great looking documentation, and a simple way to add unit tests to your code. But that's not all, as more and more people start using doctrings you can be sure that the list of docstring tools will continue to grow.</p>
<p>We all know that commenting source code and writing documentation are among the least enjoyable tasks a programmer can face. In fact the only thing worse then commenting and documenting is trying to use code with no comments and poor documentation! So do me, and yourself, a favour: start writing those docstrings.</p>
<p><a name="1">[1] http://www.python.org/dev/peps/pep-0257/#what-is-a-docstring</a><br />
<a name="2">[2] http://www.python.org/doc/essays/styleguide.html</a><br />
<a name="3">[3] http://www.python.org/doc/essays/styleguide.html</a><br />
<a name="4">[4] http://epydoc.sourceforge.net/</a><br />
<a name="5">[5] http://docutils.sourceforge.net/</a><br />
<a name="6">[6] http://docs.python.org/lib/module-doctest.html</a><br />
<a name="7">[7] http://docs.python.org/lib/doctest-finding-examples.html</a></code></p>
<div style="float:right;margin:0px 0px 0px 0px;"><a href="http://www.google.com/reader/link?url=http://www.learningpython.com/2010/01/08/introducing-docstrings/&title=Introducing Docstrings&srcTitle=learning python&srcURL=http://www.learningpython.com"target="_blank" rel=""><img border="0" src="http://www.learningpython.com/wp-content/plugins/wp-google-buzz/icon/12.png" style="opacity:1;filter:alpha(opacity=100)" onmouseover="this.style.opacity=0.8;this.filters.alpha.opacity=70" onmouseout="this.style.opacity=1;this.filters.alpha.opacity=100"/> </a></div>]]></content:encoded>
			<wfw:commentRss>http://www.learningpython.com/2010/01/08/introducing-docstrings/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>TextWidget 0.1</title>
		<link>http://www.learningpython.com/2008/09/21/textwidget-01/</link>
		<comments>http://www.learningpython.com/2008/09/21/textwidget-01/#comments</comments>
		<pubDate>Sun, 21 Sep 2008 21:41:50 +0000</pubDate>
		<dc:creator>selsine</dc:creator>
				<category><![CDATA[TextWidget]]></category>
		<category><![CDATA[pygame]]></category>
		<category><![CDATA[python]]></category>

		<guid isPermaLink="false">http://www.learningpython.com/?p=99</guid>
		<description><![CDATA[
			
				
			
		
It&#8217;s been a long time since I worked on TextWidget at all, but since someone posted a question about it I decided to fix the issue and re-release the source. But since I didn&#8217;t want to simply update the blog post I decided to give the project a proper home on google code: http://code.google.com/p/textwidget/
The project [...]]]></description>
			<content:encoded><![CDATA[<div class="tweetmeme_button" style="float: right; margin-left: 10px;">
			<a href="http://api.tweetmeme.com/share?url=http%3A%2F%2Fwww.learningpython.com%2F2008%2F09%2F21%2Ftextwidget-01%2F"><br />
				<img src="http://api.tweetmeme.com/imagebutton.gif?url=http%3A%2F%2Fwww.learningpython.com%2F2008%2F09%2F21%2Ftextwidget-01%2F&amp;style=normal" height="61" width="50" /><br />
			</a>
		</div>
<p>It&#8217;s been a long time since I worked on <a href="http://www.learningpython.com/2006/12/13/textwidget-a-simple-text-class-for-pygame/">TextWidget</a> at all, but since someone posted a question about it I decided to fix the issue and re-release the source. But since I didn&#8217;t want to simply update the blog post I decided to give the project a proper home on google code: <a href="http://code.google.com/p/textwidget/">http://code.google.com/p/textwidget/</a></p>
<p>The project is really simple and meant as an easy way for you to create &#8220;text buttons&#8221; for your PyGame projects.  It&#8217;s not meant to be the definitive way to do this, just a simple solution for people that just want to drop a class in and have working &#8220;text buttons&#8221;. It&#8217;s LGPL so you can use it in whatever way you want. If you do decide to use it please drop me an email and let me know.</p>
<p>For more information on how to use the project please take a look at the initial <a href="http://www.learningpython.com/2006/12/13/textwidget-a-simple-text-class-for-pygame/">blog post</a>.</p>
<div style="float:right;margin:0px 0px 0px 0px;"><a href="http://www.google.com/reader/link?url=http://www.learningpython.com/2008/09/21/textwidget-01/&title=TextWidget 0.1&srcTitle=learning python&srcURL=http://www.learningpython.com"target="_blank" rel=""><img border="0" src="http://www.learningpython.com/wp-content/plugins/wp-google-buzz/icon/12.png" style="opacity:1;filter:alpha(opacity=100)" onmouseover="this.style.opacity=0.8;this.filters.alpha.opacity=70" onmouseout="this.style.opacity=1;this.filters.alpha.opacity=100"/> </a></div>]]></content:encoded>
			<wfw:commentRss>http://www.learningpython.com/2008/09/21/textwidget-01/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>An Introduction to PyQt: creating GUIs with Python&#8217;s QT bindings</title>
		<link>http://www.learningpython.com/2008/09/20/an-introduction-to-pyqt/</link>
		<comments>http://www.learningpython.com/2008/09/20/an-introduction-to-pyqt/#comments</comments>
		<pubDate>Sat, 20 Sep 2008 19:21:46 +0000</pubDate>
		<dc:creator>selsine</dc:creator>
				<category><![CDATA[PyQt]]></category>
		<category><![CDATA[python]]></category>
		<category><![CDATA[gui]]></category>

		<guid isPermaLink="false">http://www.learningpython.com/?p=88</guid>
		<description><![CDATA[
			
				
			
		
By: Mark Mruss
Note: This article was first published the December 2007 issue of Python Magazine
While the command line will never cease to be useful, nothing will impress your friends more than your latest python masterpiece wrapped up in a slick cross-platform Graphical User Interface (GUI). This tutorial will show you how to create a simple [...]]]></description>
			<content:encoded><![CDATA[<div class="tweetmeme_button" style="float: right; margin-left: 10px;">
			<a href="http://api.tweetmeme.com/share?url=http%3A%2F%2Fwww.learningpython.com%2F2008%2F09%2F20%2Fan-introduction-to-pyqt%2F"><br />
				<img src="http://api.tweetmeme.com/imagebutton.gif?url=http%3A%2F%2Fwww.learningpython.com%2F2008%2F09%2F20%2Fan-introduction-to-pyqt%2F&amp;style=normal" height="61" width="50" /><br />
			</a>
		</div>
<p><strong>By: Mark Mruss</strong></p>
<p><strong>Note:</strong> This article was first published the December 2007 issue of <a href="http://www.pythonmagazine.com">Python Magazine</a></p>
<p>While the command line will never cease to be useful, nothing will impress your friends more than your latest python masterpiece wrapped up in a slick cross-platform Graphical User Interface (GUI). This tutorial will show you how to create a simple GUI in Python using PyQt4.</p>
<ol>
<li><a href="#Introduction">Introduction</a></li>
<li><a href="#InstallingPyQt4">Installing PyQt4</a></li>
<li><a href="#FirstApplication">Your First PyQt4 Application</a></li>
<li><a href="#TheMainWindow">The Main Window</a></li>
<li><a href="#AddingSomeWidgets">Adding Some Widgets</a></li>
<li><a href="#SignalHandling">Signal Handling</a></li>
<li><a href="#DisplayingAMessage">Displaying a Message</a></li>
<li><a href="#Conclusion">Conclusion</a></li>
</ol>
<p><span id="more-88"></span></p>
<h2><a name="Introduction">Introduction</a></h2>
<p>While writing console applications and modules using Python can be very enjoyable, I think that almost everyone learning Python eventually wants to do one thing: create a application with a full Graphical User Interface (GUI). Fortunately for Python users, there are a few options available to achieve this. One of the more interesting options is PyQt4, Python bindings for the fourth version of the famous cross platform application development API Qt.</p>
<p>Qt, owned by Trolltech software, is probably most famous as the foundation for the KDE window manager on Linux. PyQt4, and PyQt version 3, were created and are maintained by Riverbank software.  Qt and PyQt4 are both open source and free for open source applications, but if you wish to develop commercial applications you will need to purchase the commercial versions of both Qt and PyQt4.</p>
<p>One of the best features of Qt is that it is a cross platform library which means that it gives you easy access to the three main desktop environments: Linux, Windows, and OS X. This is an important requirement for me because when I&#8217;m developing a small open source application I want it available on as many platforms as possible. The nice thing about Qt’s latest version, Qt4, is that it also gives your GUI a native look and feel on the different operating systems.</p>
<p>This article will create a simple application to introduce you to the basic features of PyQt4. The application will consist of a single window that does the following: accepts user input, responds to a button click, and displays a message using a pop-up dialog.</p>
<h2><a name="InstallingPyQt4">Installing PyQt4</a></h2>
<p>Before installing PyQt4 you need to have Python 2.5 or newer and Qt version 4 installed. You can download Python 2.5 from the main Python website.<a href="#1">[1]</a> Qt version 4 is available from the TrollTech website&#8217;s Downloads section.<a href="#2">[2]</a> Installing PyQt4 on Linux, Windows, or OS X is relatively easy, and I know since I installed it on each of them. You can download the different PyQt4 packages from the Riverbank website, including an all in one (Qt version 4 included) installer for Windows.<a href="#3">[3]</a> There are also installation instructions in the PyQt4 online documentation that are worth a read if you are new to installing software from source.<a href="#4">[4]</a> If you are using a modern Linux distribution, you may want to consider using your package manager to install PyQt4 as it should being along all the necessary dependencies for you.</p>
<h2><a name="FirstApplication">Your First PyQt4 Application</a></h2>
<p>Now that you have PyQT4 properly installed, let’s dive right in and create an application. The first step is to start a new Python file, I called mine <code>PyQt4Intro.py</code> but you can call it whatever you like. Set it up using the following code:</p>
<div class="hl-surround" ><div class="hl-main"><pre><span class="hl-comment">#!/usr/bin/env python
</span><span class="hl-reserved">import </span><span class="hl-identifier">PyQt4

</span><span class="hl-reserved">if </span><span class="hl-identifier">__name__</span><span class="hl-default"> == </span><span class="hl-quotes">&quot;</span><span class="hl-string">__main__</span><span class="hl-quotes">&quot;</span><span class="hl-default">:
	</span><span class="hl-comment"># Someone is launching this directly
	</span><span class="hl-reserved">pass</span></pre></div></div>
<p>If you&#8217;ve read any of my other columns, you may recognize this code as a general template that I use for my Python projects. The major difference in this example is that we import PyQt4. After you have set your file up run the code. If all goes well nothing will happen. If you do get an error, something like the following, it probably means that PyQt4 is not installed properly:</p>
<div class="hl-surround" style="height:28px;"><div class="hl-main"><pre>ImportError: No module named PyQt4</pre></div></div>
<p>Remember that PyQT4 requires Python 2.5. If you have Python 2.5 and older versions of Python installed, try specifying <code>python2.5</code> when you run the script:</p>
<div class="hl-surround" style="height:28px;"><div class="hl-main"><pre>python2.5 PyQt4Intro.py</pre></div></div>
<p>Now that we have everything in order, let&#8217;s create and show a window. After all this is a GUI tutorial! If you are creating a GUI application using PyQt4 (of course, you can also create a non-GUI application using PyQt4), you will need to create a <code>QApplication</code> instance. </p>
<p>The PyQt4 documentation provides a great description of the &#8220;QApplication&#8221; class: &#8220;The QApplication class manages the GUI application&#8217;s control flow and main settings. It contains the main event loop, where all events from the window system and other sources are processed and dispatched. It also handles the application&#8217;s initialization and finalization, and provides session management. It also handles most system-wide and application-wide settings. For any GUI application that uses Qt, there is precisely one QApplication object, no matter whether the application has 0, 1, 2 or more windows at any time.&#8221;<a href="#5">[5]</a></p>
<p>What we need to do is create the one and only <code>QApplication</code> instance for our application. To do this, we will import two new modules:</p>
<div class="hl-surround" ><div class="hl-main"><pre><span class="hl-reserved">import </span><span class="hl-identifier">sys
</span><span class="hl-reserved">from </span><span class="hl-identifier">PyQt4 </span><span class="hl-reserved">import </span><span class="hl-identifier">QtGui</span></pre></div></div>
<p>The first line imports the <code>sys</code> module. This is needed to initialize the <code>QApplication</code>. The second line imports the <code>QtGui</code> module. It allows us to reference <code>QApplication</code> and other <code>QtGui</code> components. </p>
<p>In our main block, we will add the following code:</p>
<div class="hl-surround" ><div class="hl-main"><pre><span class="hl-reserved">if </span><span class="hl-identifier">__name__</span><span class="hl-default"> == </span><span class="hl-quotes">&quot;</span><span class="hl-string">__main__</span><span class="hl-quotes">&quot;</span><span class="hl-default">:
	</span><span class="hl-comment"># Someone is launching this directly
	# Create the QApplication
	</span><span class="hl-identifier">app</span><span class="hl-default"> = </span><span class="hl-identifier">QtGui</span><span class="hl-default">.</span><span class="hl-identifier">QApplication</span><span class="hl-brackets">(</span><span class="hl-identifier">sys</span><span class="hl-code">.</span><span class="hl-identifier">argv</span><span class="hl-brackets">)
	</span><span class="hl-comment"># Enter the main loop
	</span><span class="hl-identifier">app</span><span class="hl-default">.</span><span class="hl-identifier">exec_</span><span class="hl-brackets">()</span></pre></div></div>
<p>This will create the <code>QApplication</code> instance, initialized with the command-line parameters that may be passed to our script. This is a necessary parameter to the <code>QApplication</code> class and is the reason that we imported the <code>sys</code> module.  The next call is to the <code>exec</code> function which &#8220;enters the main event loop and waits until exit() is called or the main widget is destroyed&#8221;.<a href="#6">[6] </a></p>
<p>If you run the entire script at this point, which I don&#8217;t necessarily recommend since it will seem to hang, you will be running a PyQt4 application. You won&#8217;t see anything since there is no visible component. However, the script will continue to run in its main loop instead of returning right after being executed. If you do decide to run this script, use CTRL+Z to exit.</p>
<h2><a name="TheMainWindow">The Main Window</a></h2>
<p>GUI applications without a visible component are not that useful so let&#8217;s add a window to our application. We will do this by sub-classing the <code>QMainWindow</code> class. The <code>QMainWindow</code> class &#8220;provides a framework for building an application&#8217;s user interface. Qt has &#8220;QMainWindow&#8221; and its related classes for main window management. &#8220;QMainWindow&#8221; has its own layout to which you can add &#8220;QToolBars&#8221;, &#8220;QDockWindows&#8221;, a &#8220;QMenuBar&#8221;, and a &#8220;QStatusBar&#8221;.&#8221;<a href="#7">[7]</a></p>
<p><strong>Note:</strong> There are other ways to create a visible window. For example you could use a <code>QWidget</code> to accomplish much of what we are going to do. I chose to use the <code>QMainWindow</code> since it provides an application framework that you might want to use when building a full GUI application.</p>
<p>We can subclass the <code>QMainWindow</code> as follows:</p>
<div class="hl-surround" ><div class="hl-main"><pre><span class="hl-reserved">class </span><span class="hl-identifier">HelloWindow</span><span class="hl-brackets">(</span><span class="hl-identifier">QtGui</span><span class="hl-code">.</span><span class="hl-identifier">QMainWindow</span><span class="hl-brackets">)</span><span class="hl-default">:

	</span><span class="hl-reserved">def </span><span class="hl-identifier">__init__</span><span class="hl-brackets">(</span><span class="hl-identifier">self</span><span class="hl-code">, </span><span class="hl-identifier">win_parent</span><span class="hl-code"> = </span><span class="hl-reserved">None</span><span class="hl-brackets">)</span><span class="hl-default">:
		</span><span class="hl-comment">#Init the base class
		</span><span class="hl-identifier">QtGui</span><span class="hl-default">.</span><span class="hl-identifier">QMainWindow</span><span class="hl-default">.</span><span class="hl-identifier">__init__</span><span class="hl-brackets">(</span><span class="hl-identifier">self</span><span class="hl-code">, </span><span class="hl-identifier">win_parent</span><span class="hl-brackets">)</span></pre></div></div>
<p>Then in the main block we can create and show our main window like this:</p>
<div class="hl-surround" ><div class="hl-main"><pre><span class="hl-identifier">app</span><span class="hl-default"> = </span><span class="hl-identifier">QtGui</span><span class="hl-default">.</span><span class="hl-identifier">QApplication</span><span class="hl-brackets">(</span><span class="hl-identifier">sys</span><span class="hl-code">.</span><span class="hl-identifier">argv</span><span class="hl-brackets">)
</span><span class="hl-comment">#The Main window
</span><span class="hl-identifier">main_window</span><span class="hl-default"> = </span><span class="hl-identifier">HelloWindow</span><span class="hl-brackets">()
</span><span class="hl-identifier">main_window</span><span class="hl-default">.</span><span class="hl-identifier">show</span><span class="hl-brackets">()
</span><span class="hl-comment"># Enter the main loop
</span><span class="hl-identifier">app</span><span class="hl-default">.</span><span class="hl-identifier">exec_</span><span class="hl-brackets">()</span></pre></div></div>
<p>The entire source code thus far is found in Listing 1. When you run the code, you will finally be greeted with your very first PyQt4 window. It will look something similar to Figure 1.</p>
<p><strong>Listing 1</strong></p>
<div class="hl-surround" ><div class="hl-main"><pre><span class="hl-comment">#!/usr/bin/env python
</span><span class="hl-reserved">import </span><span class="hl-identifier">PyQt4
</span><span class="hl-reserved">import </span><span class="hl-identifier">sys
</span><span class="hl-reserved">from </span><span class="hl-identifier">PyQt4 </span><span class="hl-reserved">import </span><span class="hl-identifier">QtGui

</span><span class="hl-reserved">class </span><span class="hl-identifier">HelloWindow</span><span class="hl-brackets">(</span><span class="hl-identifier">QtGui</span><span class="hl-code">.</span><span class="hl-identifier">QMainWindow</span><span class="hl-brackets">)</span><span class="hl-default">:

	</span><span class="hl-reserved">def </span><span class="hl-identifier">__init__</span><span class="hl-brackets">(</span><span class="hl-identifier">self</span><span class="hl-code">, </span><span class="hl-identifier">win_parent</span><span class="hl-code"> = </span><span class="hl-reserved">None</span><span class="hl-brackets">)</span><span class="hl-default">:
		</span><span class="hl-comment">#Init the base class
		</span><span class="hl-identifier">QtGui</span><span class="hl-default">.</span><span class="hl-identifier">QMainWindow</span><span class="hl-default">.</span><span class="hl-identifier">__init__</span><span class="hl-brackets">(</span><span class="hl-identifier">self</span><span class="hl-code">, </span><span class="hl-identifier">win_parent</span><span class="hl-brackets">)

</span><span class="hl-reserved">if </span><span class="hl-identifier">__name__</span><span class="hl-default"> == </span><span class="hl-quotes">&quot;</span><span class="hl-string">__main__</span><span class="hl-quotes">&quot;</span><span class="hl-default">:
	</span><span class="hl-comment"># Someone is launching this directly
	# Create the QApplication
	</span><span class="hl-identifier">app</span><span class="hl-default"> = </span><span class="hl-identifier">QtGui</span><span class="hl-default">.</span><span class="hl-identifier">QApplication</span><span class="hl-brackets">(</span><span class="hl-identifier">sys</span><span class="hl-code">.</span><span class="hl-identifier">argv</span><span class="hl-brackets">)
	</span><span class="hl-comment">#The Main window
	</span><span class="hl-identifier">main_window</span><span class="hl-default"> = </span><span class="hl-identifier">HelloWindow</span><span class="hl-brackets">()
	</span><span class="hl-identifier">main_window</span><span class="hl-default">.</span><span class="hl-identifier">show</span><span class="hl-brackets">()
	</span><span class="hl-comment"># Enter the main loop
	</span><span class="hl-identifier">app</span><span class="hl-default">.</span><span class="hl-identifier">exec_</span><span class="hl-brackets">()</span></pre></div></div>
<div id="attachment_91" class="wp-caption alignnone" style="width: 216px"><a href="http://www.learningpython.com/wp-content/uploads/2008/09/figure1.png"><img src="http://www.learningpython.com/wp-content/uploads/2008/09/figure1.png" alt="Figure 1" title="Figure 1" width="206" height="128" class="size-medium wp-image-91" /></a><p class="wp-caption-text">Figure 1</p></div>
<h2><a name="AddingSomeWidgets">Adding Some Widgets</a></h2>
<p>A blank window is only slightly more useful then an invisible oen. Therefore our next step is to add some functionality to our window by adding some interactive widgets. In order to do this, we will set the central widget of our main window and use a &#8220;geometry manager&#8221; (or &#8220;layout manager&#8221;) class to manage the positioning of our widgets.</p>
<p>We will add a new function to our <code>HelloWindow</code> class called <code>create_widgets</code> where we will create all of our widgets. We will call this function from the <code>__init__</code> function. The first step in the <code>create_widgets</code> function is to create a widget that will serve as the &#8220;central widget&#8221; for our main window. As mentioned earlier, the <code>QMainWindow</code> class already has a built-in layout making it easy to add menus, toolbars, and other items common to applications. <code>QMainWindow</code> classes also have a &#8220;central widget&#8221; which you can think of as the main part of the application. More to the point, the &#8220;central widget&#8221; is not the toolbars, menu, or docking panes, but the actual functional area of the application. For a greater description of the &#8220;central widget&#8221; see the PyQt4 website.<a href="#8">[8]</a></p>
<p>We will create and set our &#8220;central widget&#8221; using the following code:</p>
<div class="hl-surround" ><div class="hl-main"><pre><span class="hl-reserved">def </span><span class="hl-identifier">create_widgets</span><span class="hl-brackets">(</span><span class="hl-identifier">self</span><span class="hl-brackets">)</span><span class="hl-default">:
	</span><span class="hl-identifier">central_widget</span><span class="hl-default"> = </span><span class="hl-identifier">QtGui</span><span class="hl-default">.</span><span class="hl-identifier">QWidget</span><span class="hl-brackets">()
	</span><span class="hl-identifier">self</span><span class="hl-default">.</span><span class="hl-identifier">setCentralWidget</span><span class="hl-brackets">(</span><span class="hl-identifier">central_widget</span><span class="hl-brackets">)</span></pre></div></div>
<p>So far this won&#8217;t do anything, since we still have not added anything interactive. To add interactivity, we must add widgets to our &#8220;central widget&#8221;. Rather than place the widgets in static positions, we will use a layout manager to automatically position and adjust our widgets. If you are at all familiar with modern GUI toolkits, the idea of a layout manager should be familiar to you. They serve as a way to &#8220;pack&#8221; widgets into an area where their positions will be relative to each other and to the window. When you resize the window (or area), geometry manager&#8217;s will automatically adjust the size and positions of their child widgets to accommodate the new size.</p>
<p>We will be creating three widgets in our simple application: </p>
<p>1. A <code>QLabel</code> widget to display some static text.<br />
2. A <code>QLineEdit</code> widget to let the user enter some text into an edit field.<br />
3. A <code>QPushButton</code> button widget that will pop up a dialog to display a message when the user clicks on it.</p>
<p>We will create the widgets using the following code. Notice that in the creation of the <code>QLabel</code> and <code>QPushButton</code> widgets we are also setting the text that will appear on each widget. (We can do the same for the <code>QLineEdit</code>, but for now we&#8217;ll leave it blank):</p>
<div class="hl-surround" ><div class="hl-main"><pre><span class="hl-reserved">def </span><span class="hl-identifier">create_widgets</span><span class="hl-brackets">(</span><span class="hl-identifier">self</span><span class="hl-brackets">)</span><span class="hl-default">:
	</span><span class="hl-comment">#Widgets
	</span><span class="hl-identifier">self</span><span class="hl-default">.</span><span class="hl-identifier">label</span><span class="hl-default"> = </span><span class="hl-identifier">QtGui</span><span class="hl-default">.</span><span class="hl-identifier">QLabel</span><span class="hl-brackets">(</span><span class="hl-quotes">&quot;</span><span class="hl-string">Say hello:</span><span class="hl-quotes">&quot;</span><span class="hl-brackets">)
	</span><span class="hl-identifier">self</span><span class="hl-default">.</span><span class="hl-identifier">hello_edit</span><span class="hl-default"> = </span><span class="hl-identifier">QtGui</span><span class="hl-default">.</span><span class="hl-identifier">QLineEdit</span><span class="hl-brackets">()
	</span><span class="hl-identifier">self</span><span class="hl-default">.</span><span class="hl-identifier">hello_button</span><span class="hl-default"> = </span><span class="hl-identifier">QtGui</span><span class="hl-default">.</span><span class="hl-identifier">QPushButton</span><span class="hl-brackets">(</span><span class="hl-quotes">&quot;</span><span class="hl-string">Push Me!</span><span class="hl-quotes">&quot;</span><span class="hl-brackets">)</span></pre></div></div>
<p>Next, we will create a <code>QHBoxLayout</code> instance to serve as the central widget&#8217;s layout manager. The <code>QHBoxLayout</code> class is a specific type of layout manager that lays widgets out, and manage their positions, in the horizontal direction. Once we have created the <code>QHBoxLayout</code> instance, we will add our three widgets to it. Adding widgets to a <code>QHBoxLayout</code> will pack them from left to right:</p>
<div class="hl-surround" ><div class="hl-main"><pre><span class="hl-comment">#Horizontal layout
</span><span class="hl-identifier">h_box</span><span class="hl-default"> = </span><span class="hl-identifier">QtGui</span><span class="hl-default">.</span><span class="hl-identifier">QHBoxLayout</span><span class="hl-brackets">()
</span><span class="hl-identifier">h_box</span><span class="hl-default">.</span><span class="hl-identifier">addWidget</span><span class="hl-brackets">(</span><span class="hl-identifier">self</span><span class="hl-code">.</span><span class="hl-identifier">label</span><span class="hl-brackets">)
</span><span class="hl-identifier">h_box</span><span class="hl-default">.</span><span class="hl-identifier">addWidget</span><span class="hl-brackets">(</span><span class="hl-identifier">self</span><span class="hl-code">.</span><span class="hl-identifier">hello_edit</span><span class="hl-brackets">)
</span><span class="hl-identifier">h_box</span><span class="hl-default">.</span><span class="hl-identifier">addWidget</span><span class="hl-brackets">(</span><span class="hl-identifier">self</span><span class="hl-code">.</span><span class="hl-identifier">hello_button</span><span class="hl-brackets">)</span></pre></div></div>
<p>The last step in our widget creation is to set <code>h_box</code> as the layout manager for our central widget:</p>
<div class="hl-surround" ><div class="hl-main"><pre><span class="hl-comment">#Create central widget, add layout, and set
</span><span class="hl-identifier">central_widget</span><span class="hl-default"> = </span><span class="hl-identifier">QtGui</span><span class="hl-default">.</span><span class="hl-identifier">QWidget</span><span class="hl-brackets">()
</span><span class="hl-identifier">central_widget</span><span class="hl-default">.</span><span class="hl-identifier">setLayout</span><span class="hl-brackets">(</span><span class="hl-identifier">h_box</span><span class="hl-brackets">)
</span><span class="hl-identifier">self</span><span class="hl-default">.</span><span class="hl-identifier">setCentralWidget</span><span class="hl-brackets">(</span><span class="hl-identifier">central_widget</span><span class="hl-brackets">)</span></pre></div></div>
<p>The entire code can be seen in Listing 2. When you run this code, you will finally be greeted with a window containing actual widgets. This is illustrated in Figure 2.</p>
<p><strong>Listing 2</strong></p>
<div class="hl-surround" style="height:280px;"><div class="hl-main"><pre><span class="hl-comment">#!/usr/bin/env python
</span><span class="hl-reserved">import </span><span class="hl-identifier">PyQt4
</span><span class="hl-reserved">import </span><span class="hl-identifier">sys
</span><span class="hl-reserved">from </span><span class="hl-identifier">PyQt4 </span><span class="hl-reserved">import </span><span class="hl-identifier">QtGui

</span><span class="hl-reserved">class </span><span class="hl-identifier">HelloWindow</span><span class="hl-brackets">(</span><span class="hl-identifier">QtGui</span><span class="hl-code">.</span><span class="hl-identifier">QMainWindow</span><span class="hl-brackets">)</span><span class="hl-default">:

	</span><span class="hl-reserved">def </span><span class="hl-identifier">__init__</span><span class="hl-brackets">(</span><span class="hl-identifier">self</span><span class="hl-code">, </span><span class="hl-identifier">win_parent</span><span class="hl-code"> = </span><span class="hl-reserved">None</span><span class="hl-brackets">)</span><span class="hl-default">:
		</span><span class="hl-comment">#Init the base class
		</span><span class="hl-identifier">QtGui</span><span class="hl-default">.</span><span class="hl-identifier">QMainWindow</span><span class="hl-default">.</span><span class="hl-identifier">__init__</span><span class="hl-brackets">(</span><span class="hl-identifier">self</span><span class="hl-code">, </span><span class="hl-identifier">win_parent</span><span class="hl-brackets">)
		</span><span class="hl-identifier">self</span><span class="hl-default">.</span><span class="hl-identifier">create_widgets</span><span class="hl-brackets">()

	</span><span class="hl-reserved">def </span><span class="hl-identifier">create_widgets</span><span class="hl-brackets">(</span><span class="hl-identifier">self</span><span class="hl-brackets">)</span><span class="hl-default">:
		</span><span class="hl-comment">#Widgets
		</span><span class="hl-identifier">self</span><span class="hl-default">.</span><span class="hl-identifier">label</span><span class="hl-default"> = </span><span class="hl-identifier">QtGui</span><span class="hl-default">.</span><span class="hl-identifier">QLabel</span><span class="hl-brackets">(</span><span class="hl-quotes">&quot;</span><span class="hl-string">Say hello:</span><span class="hl-quotes">&quot;</span><span class="hl-brackets">)
		</span><span class="hl-identifier">self</span><span class="hl-default">.</span><span class="hl-identifier">hello_edit</span><span class="hl-default"> = </span><span class="hl-identifier">QtGui</span><span class="hl-default">.</span><span class="hl-identifier">QLineEdit</span><span class="hl-brackets">()
		</span><span class="hl-identifier">self</span><span class="hl-default">.</span><span class="hl-identifier">hello_button</span><span class="hl-default"> = </span><span class="hl-identifier">QtGui</span><span class="hl-default">.</span><span class="hl-identifier">QPushButton</span><span class="hl-brackets">(</span><span class="hl-quotes">&quot;</span><span class="hl-string">Push Me!</span><span class="hl-quotes">&quot;</span><span class="hl-brackets">)
		</span><span class="hl-comment">#Horizontal layout
		</span><span class="hl-identifier">h_box</span><span class="hl-default"> = </span><span class="hl-identifier">QtGui</span><span class="hl-default">.</span><span class="hl-identifier">QHBoxLayout</span><span class="hl-brackets">()
		</span><span class="hl-identifier">h_box</span><span class="hl-default">.</span><span class="hl-identifier">addWidget</span><span class="hl-brackets">(</span><span class="hl-identifier">self</span><span class="hl-code">.</span><span class="hl-identifier">label</span><span class="hl-brackets">)
		</span><span class="hl-identifier">h_box</span><span class="hl-default">.</span><span class="hl-identifier">addWidget</span><span class="hl-brackets">(</span><span class="hl-identifier">self</span><span class="hl-code">.</span><span class="hl-identifier">hello_edit</span><span class="hl-brackets">)
		</span><span class="hl-identifier">h_box</span><span class="hl-default">.</span><span class="hl-identifier">addWidget</span><span class="hl-brackets">(</span><span class="hl-identifier">self</span><span class="hl-code">.</span><span class="hl-identifier">hello_button</span><span class="hl-brackets">)
		</span><span class="hl-comment">#Create central widget, add layout and set
		</span><span class="hl-identifier">central_widget</span><span class="hl-default"> = </span><span class="hl-identifier">QtGui</span><span class="hl-default">.</span><span class="hl-identifier">QWidget</span><span class="hl-brackets">()
		</span><span class="hl-identifier">central_widget</span><span class="hl-default">.</span><span class="hl-identifier">setLayout</span><span class="hl-brackets">(</span><span class="hl-identifier">h_box</span><span class="hl-brackets">)
		</span><span class="hl-identifier">self</span><span class="hl-default">.</span><span class="hl-identifier">setCentralWidget</span><span class="hl-brackets">(</span><span class="hl-identifier">central_widget</span><span class="hl-brackets">)

</span><span class="hl-reserved">if </span><span class="hl-identifier">__name__</span><span class="hl-default"> == </span><span class="hl-quotes">&quot;</span><span class="hl-string">__main__</span><span class="hl-quotes">&quot;</span><span class="hl-default">:
	</span><span class="hl-comment"># Someone is launching this directly
	# Create the QApplication
	</span><span class="hl-identifier">app</span><span class="hl-default"> = </span><span class="hl-identifier">QtGui</span><span class="hl-default">.</span><span class="hl-identifier">QApplication</span><span class="hl-brackets">(</span><span class="hl-identifier">sys</span><span class="hl-code">.</span><span class="hl-identifier">argv</span><span class="hl-brackets">)
	</span><span class="hl-comment">#The Main window
	</span><span class="hl-identifier">main_window</span><span class="hl-default"> = </span><span class="hl-identifier">HelloWindow</span><span class="hl-brackets">()
	</span><span class="hl-identifier">main_window</span><span class="hl-default">.</span><span class="hl-identifier">show</span><span class="hl-brackets">()
	</span><span class="hl-comment"># Enter the main loop
	</span><span class="hl-identifier">app</span><span class="hl-default">.</span><span class="hl-identifier">exec_</span><span class="hl-brackets">()</span></pre></div></div>
<div id="attachment_92" class="wp-caption alignnone" style="width: 296px"><a href="http://www.learningpython.com/wp-content/uploads/2008/09/figure2.png"><img src="http://www.learningpython.com/wp-content/uploads/2008/09/figure2.png" alt="Figure 2" title="Figure 2" width="286" height="128" class="size-medium wp-image-92" /></a><p class="wp-caption-text">Figure 2</p></div>
<h2><a name="SignalHandling">Signal Handling</a></h2>
<p>Responding to the user’s interaction with the GUI is something that must be done in all GUI applications. Therefore the next step in constructing a GUI application is signal or event handling. If you are unfamiliar with these terms you can thing of it his way: when the end user interacts with your GUI, her interaction will causes signals to be sent to your application. So if she clicks on a button the clicked() signal will be sent. If your application wants to do something when that button is clicked, then you will have to handle that widgets <code>clicked()</code> signal.  In our example, we are going to show a pop up a dialog when the user clicks on our button widget.</p>
<p>I find connecting to signals in PyQt4 a bit odd because of a built in macro that needs to be called but the process is relatively easy so I shouldn&#8217;t complain too much. The idea is similar to that of other Python GUI toolkits: you connect functions that you have written to signals or events that are emitted by a widget. So whenever a widget emits a signal that has been connected to a function, that function will be called.</p>
<p><strong>Note:</strong> Qt goes a bit further with the idea of built-in &#8220;slots&#8221; but for the sake of this tutorial we will be ignoring them. For more information on &#8220;slots&#8221; please see the PyQt4 documentation.</p>
<p>In order for the &#8220;QPushButton&#8221; to do something when pushed, we have to connect a function in our <code>HelloWindow</code> class with the <code>clicked</code> signal.  To do this, we need to call the <code>QObject</code> classes <code>connect</code> static function. We must tell it three things: </p>
<p>1. The <code>QWidget</code> that will emit the signal.<br />
2. The signal that we want to connect to.<br />
3. The function that should be called when the <code>QWidget</code> emits the signal.</p>
<p>In our example, we will do this like so:</p>
<div class="hl-surround" ><div class="hl-main"><pre><span class="hl-comment">#connect signal
</span><span class="hl-identifier">QtCore</span><span class="hl-default">.</span><span class="hl-identifier">QObject</span><span class="hl-default">.</span><span class="hl-identifier">connect</span><span class="hl-brackets">(</span><span class="hl-identifier">self</span><span class="hl-code">.</span><span class="hl-identifier">hello_button</span><span class="hl-code">
	, </span><span class="hl-identifier">QtCore</span><span class="hl-code">.</span><span class="hl-identifier">SIGNAL</span><span class="hl-brackets">(</span><span class="hl-quotes">&quot;</span><span class="hl-string">clicked()</span><span class="hl-quotes">&quot;</span><span class="hl-brackets">)</span><span class="hl-code">
	, </span><span class="hl-identifier">self</span><span class="hl-code">.</span><span class="hl-identifier">on_hello_clicked</span><span class="hl-brackets">)</span></pre></div></div>
<p><strong>Note:</strong> We could just as easily have called <code>self.connect</code> since a <code>QMainWindow</code> is a descendant of the <code>QObject</code> class.</p>
<p><code>QtCore.SIGNAL</code> is a macro that you have to use for the second parameter. It accepts the signal name as a string (in this case <code>clicked()</code>) and converts it into an object that is required for the signal connection. The documentation is a bit sparse regarding exactly what the macro does, but luckily for us we don&#8217;t really need to know the details.</p>
<p>In order for this code to compile, we also have to import the <code>QtCore</code> module:</p>
<div class="hl-surround" style="height:28px;"><div class="hl-main"><pre><span class="hl-reserved">from </span><span class="hl-identifier">PyQt4 </span><span class="hl-reserved">import </span><span class="hl-identifier">QtCore</span></pre></div></div>
<p>We also have to add a new function to the <code>HelloWindow</code> class. This is the function <code>on_hello_clicked</code> that will respond to the <code>clicked()</code> signal:</p>
<div class="hl-surround" ><div class="hl-main"><pre><span class="hl-reserved">def </span><span class="hl-identifier">on_hello_clicked</span><span class="hl-brackets">(</span><span class="hl-identifier">self</span><span class="hl-brackets">)</span><span class="hl-default">:
	</span><span class="hl-reserved">print </span><span class="hl-quotes">&quot;</span><span class="hl-string">Clicked</span><span class="hl-quotes">&quot;</span></pre></div></div>
<p>When you run the code in Listing 3, you will see &#8220;Clicked&#8221; printed out to the command line every time you click the &#8220;Push Me!&#8221; button.</p>
<p><strong>Listing 3</strong></p>
<div class="hl-surround" style="height:280px;"><div class="hl-main"><pre><span class="hl-comment">#!/usr/bin/env python
</span><span class="hl-reserved">import </span><span class="hl-identifier">PyQt4
</span><span class="hl-reserved">import </span><span class="hl-identifier">sys
</span><span class="hl-reserved">from </span><span class="hl-identifier">PyQt4 </span><span class="hl-reserved">import </span><span class="hl-identifier">QtGui
</span><span class="hl-reserved">from </span><span class="hl-identifier">PyQt4 </span><span class="hl-reserved">import </span><span class="hl-identifier">QtCore

</span><span class="hl-reserved">class </span><span class="hl-identifier">HelloWindow</span><span class="hl-brackets">(</span><span class="hl-identifier">QtGui</span><span class="hl-code">.</span><span class="hl-identifier">QMainWindow</span><span class="hl-brackets">)</span><span class="hl-default">:

	</span><span class="hl-reserved">def </span><span class="hl-identifier">__init__</span><span class="hl-brackets">(</span><span class="hl-identifier">self</span><span class="hl-code">, </span><span class="hl-identifier">win_parent</span><span class="hl-code"> = </span><span class="hl-reserved">None</span><span class="hl-brackets">)</span><span class="hl-default">:
		</span><span class="hl-comment">#Init the base class
		</span><span class="hl-identifier">QtGui</span><span class="hl-default">.</span><span class="hl-identifier">QMainWindow</span><span class="hl-default">.</span><span class="hl-identifier">__init__</span><span class="hl-brackets">(</span><span class="hl-identifier">self</span><span class="hl-code">, </span><span class="hl-identifier">win_parent</span><span class="hl-brackets">)
		</span><span class="hl-identifier">self</span><span class="hl-default">.</span><span class="hl-identifier">create_widgets</span><span class="hl-brackets">()


	</span><span class="hl-reserved">def </span><span class="hl-identifier">create_widgets</span><span class="hl-brackets">(</span><span class="hl-identifier">self</span><span class="hl-brackets">)</span><span class="hl-default">:
		</span><span class="hl-comment">#Widgets
		</span><span class="hl-identifier">self</span><span class="hl-default">.</span><span class="hl-identifier">label</span><span class="hl-default"> = </span><span class="hl-identifier">QtGui</span><span class="hl-default">.</span><span class="hl-identifier">QLabel</span><span class="hl-brackets">(</span><span class="hl-quotes">&quot;</span><span class="hl-string">Say hello:</span><span class="hl-quotes">&quot;</span><span class="hl-brackets">)
		</span><span class="hl-identifier">self</span><span class="hl-default">.</span><span class="hl-identifier">hello_edit</span><span class="hl-default"> = </span><span class="hl-identifier">QtGui</span><span class="hl-default">.</span><span class="hl-identifier">QLineEdit</span><span class="hl-brackets">()
		</span><span class="hl-identifier">self</span><span class="hl-default">.</span><span class="hl-identifier">hello_button</span><span class="hl-default"> = </span><span class="hl-identifier">QtGui</span><span class="hl-default">.</span><span class="hl-identifier">QPushButton</span><span class="hl-brackets">(</span><span class="hl-quotes">&quot;</span><span class="hl-string">Push Me!</span><span class="hl-quotes">&quot;</span><span class="hl-brackets">)

		</span><span class="hl-comment">#connect signal
		</span><span class="hl-identifier">QtCore</span><span class="hl-default">.</span><span class="hl-identifier">QObject</span><span class="hl-default">.</span><span class="hl-identifier">connect</span><span class="hl-brackets">(</span><span class="hl-identifier">self</span><span class="hl-code">.</span><span class="hl-identifier">hello_button</span><span class="hl-code">
			, </span><span class="hl-identifier">QtCore</span><span class="hl-code">.</span><span class="hl-identifier">SIGNAL</span><span class="hl-brackets">(</span><span class="hl-quotes">&quot;</span><span class="hl-string">clicked()</span><span class="hl-quotes">&quot;</span><span class="hl-brackets">)</span><span class="hl-code">
			, </span><span class="hl-identifier">self</span><span class="hl-code">.</span><span class="hl-identifier">on_hello_clicked</span><span class="hl-brackets">)


		</span><span class="hl-comment">#Horizontal layout
		</span><span class="hl-identifier">h_box</span><span class="hl-default"> = </span><span class="hl-identifier">QtGui</span><span class="hl-default">.</span><span class="hl-identifier">QHBoxLayout</span><span class="hl-brackets">()
		</span><span class="hl-identifier">h_box</span><span class="hl-default">.</span><span class="hl-identifier">addWidget</span><span class="hl-brackets">(</span><span class="hl-identifier">self</span><span class="hl-code">.</span><span class="hl-identifier">label</span><span class="hl-brackets">)
		</span><span class="hl-identifier">h_box</span><span class="hl-default">.</span><span class="hl-identifier">addWidget</span><span class="hl-brackets">(</span><span class="hl-identifier">self</span><span class="hl-code">.</span><span class="hl-identifier">hello_edit</span><span class="hl-brackets">)
		</span><span class="hl-identifier">h_box</span><span class="hl-default">.</span><span class="hl-identifier">addWidget</span><span class="hl-brackets">(</span><span class="hl-identifier">self</span><span class="hl-code">.</span><span class="hl-identifier">hello_button</span><span class="hl-brackets">)
		</span><span class="hl-comment">#Create central widget, add layout and set
		</span><span class="hl-identifier">central_widget</span><span class="hl-default"> = </span><span class="hl-identifier">QtGui</span><span class="hl-default">.</span><span class="hl-identifier">QWidget</span><span class="hl-brackets">()
		</span><span class="hl-identifier">central_widget</span><span class="hl-default">.</span><span class="hl-identifier">setLayout</span><span class="hl-brackets">(</span><span class="hl-identifier">h_box</span><span class="hl-brackets">)
		</span><span class="hl-identifier">self</span><span class="hl-default">.</span><span class="hl-identifier">setCentralWidget</span><span class="hl-brackets">(</span><span class="hl-identifier">central_widget</span><span class="hl-brackets">)

	</span><span class="hl-reserved">def </span><span class="hl-identifier">on_hello_clicked</span><span class="hl-brackets">(</span><span class="hl-identifier">self</span><span class="hl-brackets">)</span><span class="hl-default">:
		</span><span class="hl-reserved">print </span><span class="hl-quotes">&quot;</span><span class="hl-string">Clicked</span><span class="hl-quotes">&quot;
		
</span><span class="hl-reserved">if </span><span class="hl-identifier">__name__</span><span class="hl-default"> == </span><span class="hl-quotes">&quot;</span><span class="hl-string">__main__</span><span class="hl-quotes">&quot;</span><span class="hl-default">:
	</span><span class="hl-comment"># Someone is launching this directly
	# Create the QApplication
	</span><span class="hl-identifier">app</span><span class="hl-default"> = </span><span class="hl-identifier">QtGui</span><span class="hl-default">.</span><span class="hl-identifier">QApplication</span><span class="hl-brackets">(</span><span class="hl-identifier">sys</span><span class="hl-code">.</span><span class="hl-identifier">argv</span><span class="hl-brackets">)
	</span><span class="hl-comment">#The Main window
	</span><span class="hl-identifier">main_window</span><span class="hl-default"> = </span><span class="hl-identifier">HelloWindow</span><span class="hl-brackets">()
	</span><span class="hl-identifier">main_window</span><span class="hl-default">.</span><span class="hl-identifier">show</span><span class="hl-brackets">()
	</span><span class="hl-comment"># Enter the main loop
	</span><span class="hl-identifier">app</span><span class="hl-default">.</span><span class="hl-identifier">exec_</span><span class="hl-brackets">()</span></pre></div></div>
<h2><a name="DisplayingAMessage">Displaying a Message</a></h2>
<p>Now that we have a function connected to the clicking of the button widget we need to read the text from the <code>QLineEdit</code> widget and display it to the user. Fortunately both tasks are quite easy in PyQt4. </p>
<p>In order to get the text from a <code>QLineEdit</code> widget, the <code>QLineEdit</code> classes member function <code>displayText</code> needs to be called. The <code>displayText</code> function simply returns the contents of the <code>QLineEdit</code> widget.</p>
<p>Showing a pop-up dialog using PyQt4 is just as easy as getting the contents of a <code>QLineEdit</code> widget, thanks to the <code>QMesssageBox</code> classes static function <code>information</code>.  This function allows you to set the title, text and what buttons are on a simple &#8220;information dialog&#8221;.  Calling it from our PyQt4 application in response to the button click is very simple:</p>
<div class="hl-surround" ><div class="hl-main"><pre><span class="hl-reserved">def </span><span class="hl-identifier">on_hello_clicked</span><span class="hl-brackets">(</span><span class="hl-identifier">self</span><span class="hl-brackets">)</span><span class="hl-default">:
	</span><span class="hl-identifier">QtGui</span><span class="hl-default">.</span><span class="hl-identifier">QMessageBox</span><span class="hl-default">.</span><span class="hl-identifier">information</span><span class="hl-brackets">(</span><span class="hl-identifier">self</span><span class="hl-code">
		, </span><span class="hl-quotes">&quot;</span><span class="hl-string">Hello!</span><span class="hl-quotes">&quot;</span><span class="hl-code">
		, </span><span class="hl-quotes">&quot;</span><span class="hl-string">Hello %s</span><span class="hl-quotes">&quot;</span><span class="hl-code"> % </span><span class="hl-identifier">self</span><span class="hl-code">.</span><span class="hl-identifier">hello_edit</span><span class="hl-code">.</span><span class="hl-identifier">displayText</span><span class="hl-brackets">()</span><span class="hl-code">
		, </span><span class="hl-identifier">QtGui</span><span class="hl-code">.</span><span class="hl-identifier">QMessageBox</span><span class="hl-code">.</span><span class="hl-identifier">Ok</span><span class="hl-brackets">)</span></pre></div></div>
<p>In this code, we call the information function, set its title text to be &#8220;Hello!&#8221;, set its main message to be &#8220;Hello &#8221; followed by the contents of the <code>hello_edit</code> <code>QInputEdit</code>, and give it one button, an &#8220;ok&#8221; button. All of the code is found in Listing 4. What this looks like running on Linux, Windows and OS X can be seen in Figure 3, Figure 4, and Figure 5 respectively.</p>
<p><strong>Listing 4</strong></p>
<div class="hl-surround" style="height:280px;"><div class="hl-main"><pre><span class="hl-comment">#!/usr/bin/env python
</span><span class="hl-reserved">import </span><span class="hl-identifier">PyQt4
</span><span class="hl-reserved">import </span><span class="hl-identifier">sys
</span><span class="hl-reserved">from </span><span class="hl-identifier">PyQt4 </span><span class="hl-reserved">import </span><span class="hl-identifier">QtGui
</span><span class="hl-reserved">from </span><span class="hl-identifier">PyQt4 </span><span class="hl-reserved">import </span><span class="hl-identifier">QtCore

</span><span class="hl-reserved">class </span><span class="hl-identifier">HelloWindow</span><span class="hl-brackets">(</span><span class="hl-identifier">QtGui</span><span class="hl-code">.</span><span class="hl-identifier">QMainWindow</span><span class="hl-brackets">)</span><span class="hl-default">:

	</span><span class="hl-reserved">def </span><span class="hl-identifier">__init__</span><span class="hl-brackets">(</span><span class="hl-identifier">self</span><span class="hl-code">, </span><span class="hl-identifier">win_parent</span><span class="hl-code"> = </span><span class="hl-reserved">None</span><span class="hl-brackets">)</span><span class="hl-default">:
		</span><span class="hl-comment">#Init the base class
		</span><span class="hl-identifier">QtGui</span><span class="hl-default">.</span><span class="hl-identifier">QMainWindow</span><span class="hl-default">.</span><span class="hl-identifier">__init__</span><span class="hl-brackets">(</span><span class="hl-identifier">self</span><span class="hl-code">, </span><span class="hl-identifier">win_parent</span><span class="hl-brackets">)
		</span><span class="hl-identifier">self</span><span class="hl-default">.</span><span class="hl-identifier">create_widgets</span><span class="hl-brackets">()


	</span><span class="hl-reserved">def </span><span class="hl-identifier">create_widgets</span><span class="hl-brackets">(</span><span class="hl-identifier">self</span><span class="hl-brackets">)</span><span class="hl-default">:
		</span><span class="hl-comment">#Widgets
		</span><span class="hl-identifier">self</span><span class="hl-default">.</span><span class="hl-identifier">label</span><span class="hl-default"> = </span><span class="hl-identifier">QtGui</span><span class="hl-default">.</span><span class="hl-identifier">QLabel</span><span class="hl-brackets">(</span><span class="hl-quotes">&quot;</span><span class="hl-string">Say hello:</span><span class="hl-quotes">&quot;</span><span class="hl-brackets">)
		</span><span class="hl-identifier">self</span><span class="hl-default">.</span><span class="hl-identifier">hello_edit</span><span class="hl-default"> = </span><span class="hl-identifier">QtGui</span><span class="hl-default">.</span><span class="hl-identifier">QLineEdit</span><span class="hl-brackets">()
		</span><span class="hl-identifier">self</span><span class="hl-default">.</span><span class="hl-identifier">hello_button</span><span class="hl-default"> = </span><span class="hl-identifier">QtGui</span><span class="hl-default">.</span><span class="hl-identifier">QPushButton</span><span class="hl-brackets">(</span><span class="hl-quotes">&quot;</span><span class="hl-string">Push Me!</span><span class="hl-quotes">&quot;</span><span class="hl-brackets">)

		</span><span class="hl-comment">#connect signal
		</span><span class="hl-identifier">QtCore</span><span class="hl-default">.</span><span class="hl-identifier">QObject</span><span class="hl-default">.</span><span class="hl-identifier">connect</span><span class="hl-brackets">(</span><span class="hl-identifier">self</span><span class="hl-code">.</span><span class="hl-identifier">hello_button</span><span class="hl-code">
			, </span><span class="hl-identifier">QtCore</span><span class="hl-code">.</span><span class="hl-identifier">SIGNAL</span><span class="hl-brackets">(</span><span class="hl-quotes">&quot;</span><span class="hl-string">clicked()</span><span class="hl-quotes">&quot;</span><span class="hl-brackets">)</span><span class="hl-code">
			, </span><span class="hl-identifier">self</span><span class="hl-code">.</span><span class="hl-identifier">on_hello_clicked</span><span class="hl-brackets">)


		</span><span class="hl-comment">#Horizontal layout
		</span><span class="hl-identifier">h_box</span><span class="hl-default"> = </span><span class="hl-identifier">QtGui</span><span class="hl-default">.</span><span class="hl-identifier">QHBoxLayout</span><span class="hl-brackets">()
		</span><span class="hl-identifier">h_box</span><span class="hl-default">.</span><span class="hl-identifier">addWidget</span><span class="hl-brackets">(</span><span class="hl-identifier">self</span><span class="hl-code">.</span><span class="hl-identifier">label</span><span class="hl-brackets">)
		</span><span class="hl-identifier">h_box</span><span class="hl-default">.</span><span class="hl-identifier">addWidget</span><span class="hl-brackets">(</span><span class="hl-identifier">self</span><span class="hl-code">.</span><span class="hl-identifier">hello_edit</span><span class="hl-brackets">)
		</span><span class="hl-identifier">h_box</span><span class="hl-default">.</span><span class="hl-identifier">addWidget</span><span class="hl-brackets">(</span><span class="hl-identifier">self</span><span class="hl-code">.</span><span class="hl-identifier">hello_button</span><span class="hl-brackets">)
		</span><span class="hl-comment">#Create central widget, add layout and set
		</span><span class="hl-identifier">central_widget</span><span class="hl-default"> = </span><span class="hl-identifier">QtGui</span><span class="hl-default">.</span><span class="hl-identifier">QWidget</span><span class="hl-brackets">()
		</span><span class="hl-identifier">central_widget</span><span class="hl-default">.</span><span class="hl-identifier">setLayout</span><span class="hl-brackets">(</span><span class="hl-identifier">h_box</span><span class="hl-brackets">)
		</span><span class="hl-identifier">self</span><span class="hl-default">.</span><span class="hl-identifier">setCentralWidget</span><span class="hl-brackets">(</span><span class="hl-identifier">central_widget</span><span class="hl-brackets">)

	</span><span class="hl-reserved">def </span><span class="hl-identifier">on_hello_clicked</span><span class="hl-brackets">(</span><span class="hl-identifier">self</span><span class="hl-brackets">)</span><span class="hl-default">:
		</span><span class="hl-identifier">QtGui</span><span class="hl-default">.</span><span class="hl-identifier">QMessageBox</span><span class="hl-default">.</span><span class="hl-identifier">information</span><span class="hl-brackets">(</span><span class="hl-identifier">self</span><span class="hl-code">
			, </span><span class="hl-quotes">&quot;</span><span class="hl-string">Hello!</span><span class="hl-quotes">&quot;</span><span class="hl-code">
			, </span><span class="hl-quotes">&quot;</span><span class="hl-string">Hello %s</span><span class="hl-quotes">&quot;</span><span class="hl-code"> % </span><span class="hl-identifier">self</span><span class="hl-code">.</span><span class="hl-identifier">hello_edit</span><span class="hl-code">.</span><span class="hl-identifier">displayText</span><span class="hl-brackets">()</span><span class="hl-code">
			, </span><span class="hl-identifier">QtGui</span><span class="hl-code">.</span><span class="hl-identifier">QMessageBox</span><span class="hl-code">.</span><span class="hl-identifier">Ok</span><span class="hl-brackets">)

</span><span class="hl-reserved">if </span><span class="hl-identifier">__name__</span><span class="hl-default"> == </span><span class="hl-quotes">&quot;</span><span class="hl-string">__main__</span><span class="hl-quotes">&quot;</span><span class="hl-default">:
	</span><span class="hl-comment"># Someone is launching this directly
	# Create the QApplication
	</span><span class="hl-identifier">app</span><span class="hl-default"> = </span><span class="hl-identifier">QtGui</span><span class="hl-default">.</span><span class="hl-identifier">QApplication</span><span class="hl-brackets">(</span><span class="hl-identifier">sys</span><span class="hl-code">.</span><span class="hl-identifier">argv</span><span class="hl-brackets">)
	</span><span class="hl-comment">#The Main window
	</span><span class="hl-identifier">main_window</span><span class="hl-default"> = </span><span class="hl-identifier">HelloWindow</span><span class="hl-brackets">()
	</span><span class="hl-identifier">main_window</span><span class="hl-default">.</span><span class="hl-identifier">show</span><span class="hl-brackets">()
	</span><span class="hl-comment"># Enter the main loop
	</span><span class="hl-identifier">app</span><span class="hl-default">.</span><span class="hl-identifier">exec_</span><span class="hl-brackets">()</span></pre></div></div>
<div id="attachment_93" class="wp-caption alignnone" style="width: 310px"><a href="http://www.learningpython.com/wp-content/uploads/2008/09/figure3.png"><img src="http://www.learningpython.com/wp-content/uploads/2008/09/figure3-300x217.png" alt="Figure 3" title="Figure 3" width="300" height="217" class="size-medium wp-image-93" /></a><p class="wp-caption-text">Figure 3</p></div>
<div id="attachment_94" class="wp-caption alignnone" style="width: 310px"><a href="http://www.learningpython.com/wp-content/uploads/2008/09/figure4.png"><img src="http://www.learningpython.com/wp-content/uploads/2008/09/figure4-300x220.png" alt="Figure 4" title="Figure 4" width="300" height="220" class="size-medium wp-image-94" /></a><p class="wp-caption-text">Figure 4</p></div>
<div id="attachment_95" class="wp-caption alignnone" style="width: 310px"><a href="http://www.learningpython.com/wp-content/uploads/2008/09/figure5.png"><img src="http://www.learningpython.com/wp-content/uploads/2008/09/figure5-300x230.png" alt="Figure 5" title="Figure 5" width="300" height="230" class="size-medium wp-image-95" /></a><p class="wp-caption-text">Figure 5</p></div>
<h2><a name="Conclusion">Conclusion</a></h2>
<p>That&#8217;s it for this quick introduction to PyQt4. All-in-all, I was pleasantly surprised by PyQt4. Even during my first foray into the toolkit, I found it very straightforward and was able to get things going in a matter of minutes. Granted, what I was trying to accomplish was pretty simple, but it&#8217;s always a good sign when doing something simple is easy!</p>
<p>You should now have enough information to go and create your very own &#8220;GUIfied&#8221; applications. Of course, there is much, much more to PyQt4 than I have covered in this tutorial. But if you use the PyQt4 documentation and the fundamentals from this tutorial, you shouldn&#8217;t have much trouble moving forward.</p>
<p><a name="1">[1]</a> <a href="http://www.python.org/download/">http://www.python.org/download/</a><br />
<a name="2">[2]</a> <a href="http://www.riverbankcomputing.co.uk/pyqt/download.php">http://www.riverbankcomputing.co.uk/pyqt/download.php</a><br />
<a name="3">[3]</a> <a href="http://trolltech.com/downloads">http://trolltech.com/downloads</a><br />
<a name="4">[4]</a> <a href="http://www.riverbankcomputing.com/Docs/PyQt4/pyqt4ref.html#installing-pyqt">http://www.riverbankcomputing.com/Docs/PyQt4/pyqt4ref.html#installing-pyqt</a><br />
<a name="5">[5]</a> <a href="http://www.riverbankcomputing.com/Docs/PyQt4/html/qapplication.html">http://www.riverbankcomputing.com/Docs/PyQt4/html/qapplication.html</a><br />
<a name="6">[6]</a> <a href="http://www.riverbankcomputing.com/Docs/PyQt4/html/qapplication.html#exec">http://www.riverbankcomputing.com/Docs/PyQt4/html/qapplication.html#exec</a><br />
<a name="7">[7]</a> <a href="http://www.riverbankcomputing.com/Docs/PyQt4/html/qmainwindow.html#details">http://www.riverbankcomputing.com/Docs/PyQt4/html/qmainwindow.html#details</a><br />
<a name="8">[8]</a> <a href="http://www.riverbankcomputing.com/Docs/PyQt4/html/qmainwindow.html#details">http://www.riverbankcomputing.com/Docs/PyQt4/html/qmainwindow.html#details</a></p>
<div style="float:right;margin:0px 0px 0px 0px;"><a href="http://www.google.com/reader/link?url=http://www.learningpython.com/2008/09/20/an-introduction-to-pyqt/&title=An Introduction to PyQt: creating GUIs with Python's QT bindings&srcTitle=learning python&srcURL=http://www.learningpython.com"target="_blank" rel=""><img border="0" src="http://www.learningpython.com/wp-content/plugins/wp-google-buzz/icon/12.png" style="opacity:1;filter:alpha(opacity=100)" onmouseover="this.style.opacity=0.8;this.filters.alpha.opacity=70" onmouseout="this.style.opacity=1;this.filters.alpha.opacity=100"/> </a></div>]]></content:encoded>
			<wfw:commentRss>http://www.learningpython.com/2008/09/20/an-introduction-to-pyqt/feed/</wfw:commentRss>
		<slash:comments>12</slash:comments>
		</item>
		<item>
		<title>Level Editor 0.3 (Dodger)</title>
		<link>http://www.learningpython.com/2008/06/22/level-editor-03-dodger/</link>
		<comments>http://www.learningpython.com/2008/06/22/level-editor-03-dodger/#comments</comments>
		<pubDate>Mon, 23 Jun 2008 03:23:27 +0000</pubDate>
		<dc:creator>selsine</dc:creator>
				<category><![CDATA[beginnings]]></category>
		<category><![CDATA[game engine]]></category>
		<category><![CDATA[python]]></category>
		<category><![CDATA[Dodger]]></category>
		<category><![CDATA[level editor]]></category>

		<guid isPermaLink="false">http://www.learningpython.com/?p=77</guid>
		<description><![CDATA[
			
				
			
		
I know it&#8217;s been a while and for that I apologize the last few months have been pretty crazy around here&#8230;although I&#8217;m starting to see a trend with life in general lately, namely that it&#8217;s always crazy.
I&#8217;ve been busy with work, Python Magazine, my wife, trips to Dallas, and yes whenever I get a chance [...]]]></description>
			<content:encoded><![CDATA[<div class="tweetmeme_button" style="float: right; margin-left: 10px;">
			<a href="http://api.tweetmeme.com/share?url=http%3A%2F%2Fwww.learningpython.com%2F2008%2F06%2F22%2Flevel-editor-03-dodger%2F"><br />
				<img src="http://api.tweetmeme.com/imagebutton.gif?url=http%3A%2F%2Fwww.learningpython.com%2F2008%2F06%2F22%2Flevel-editor-03-dodger%2F&amp;style=normal" height="61" width="50" /><br />
			</a>
		</div>
<p>I know it&#8217;s been a while and for that I apologize the last few months have been pretty crazy around here&#8230;although I&#8217;m starting to see a trend with life in general lately, namely that it&#8217;s always crazy.</p>
<p>I&#8217;ve been busy with work, <a href="http://pymag.phparch.com/">Python Magazine</a>, my wife, trips to Dallas, and yes whenever I get a chance this slowly growing level editor. Let&#8217;s see what I&#8217;ve been working on for the last little while:</p>
<p><strong>Name</strong>: There has a been a name for the editor ever since I started working on it. I wasn&#8217;t sure if I was going to think up something really cool and change, or leave it. Turns out I just left it.</p>
<p>So from this point forward this project is christened: &#8220;Dodger&#8221;, or probably more correctly: &#8220;Dodger Level Editor&#8221;.</p>
<p>The name has its roots in the name of one of my cats and a history in the multitudes of level editors and game engines that I have tried to create in the past, but I wont&#8217; go into that. So Dodger it is.</p>
<p><strong>Saving and Loading</strong>: Saving and loading in the default YAML project type now really works. I still need to put in support for optional project types: XML, JSON, and other formats</p>
<p><a href="http://www.learningpython.com/wp-content/uploads/2008/06/editor_03.png"><img class="alignnone size-medium wp-image-78" title="welcome dialog" src="http://www.learningpython.com/wp-content/uploads/2008/06/editor_03-300x210.png" alt="dodger editor welcome dialog" width="300" height="210" /></a></p>
<p><strong>Welcome Dialog</strong>: This was a real pain, but it&#8217;s made the last while so much easier. I added a working (at least I hope) welcome dialog with a way to create new projects, open old ones, and a recent file list. The recent file list really makes testing easier for me.</p>
<p><a href="http://www.learningpython.com/wp-content/uploads/2008/06/editor_04.png"><img class="alignnone size-medium wp-image-79" title="rect tracking" src="http://www.learningpython.com/wp-content/uploads/2008/06/editor_04-300x210.png" alt="dodger editor rect tracking" width="300" height="210" /></a></p>
<p><strong>Rect tracking</strong>: Rect tracking is finally working properly. I&#8217;ve had the rect tracker in there for a while but it didn&#8217;t really do anything until now.</p>
<p><a href="http://www.learningpython.com/wp-content/uploads/2008/06/editor_05.png"><img class="alignnone size-medium wp-image-80" title="Multiple Selection" src="http://www.learningpython.com/wp-content/uploads/2008/06/editor_05-300x210.png" alt="dodger editor multiple selection" width="300" height="210" /></a></p>
<p><strong>Multiple Selection/Multiple Properties</strong>: I&#8217;ve also finally got multiple selection going, which is what makes the rect tracker actually useful. You can select multiple sprties, move them around and add properties to all of them.</p>
<p><strong>Remove Properties</strong>: Now you can remove custom properties that you have added. This was a must but I was lazy and left it for a while.</p>
<p><strong>Steps towards being made public</strong>: A lot of the changes (and I do mean a lot) that I&#8217;ve been making have been behind the scenes. There has been a lot of refactoring and reorganizing of the code, often the result of quick and dirty implementations that I made earlier (sigh). I&#8217;ve also started working on getting the distribution of this editor going so that other people can use/develop it.</p>
<p>I&#8217;ve added support for zc.Buildout so that if anyone wants to develop they can quickly gather dependencies and won&#8217;t have to install the editor system wide, not that you have to anyways but zc.Buildout is really neat.</p>
<p>I&#8217;ve also worked on the license (GPLv3) and setup.py and README and all of that. None of it&#8217;s done but it&#8217;s working its way forward.</p>
<p><strong>Faster</strong>: It&#8217;s also much faster now. None of you have used it so you&#8217;ll probably think it&#8217;s slow, but trust me it&#8217;s much faster then it was before.</p>
<p><strong>Bugs</strong>: There have been loads of bugs that have been fixed and created. Plus one doozy related to<br />
changes made to pyglet. Not pyglets fault but it took a long time to figure out what the issue was.</p>
<p><strong>Google Code</strong>: The project has a temporary homepage over at google code: <a href="http://code.google.com/p/dodger-editor/">http://code.google.com/p/dodger-editor/</a> There&#8217;s nothing there yet but over time I will start to host the project there so that people can easily download it. I&#8217;ll still post updates here until the site has a full-time home.</p>
<p>I&#8217;m going to use Mercurial for the revision control system for the project so the CVS support at the google code site will just be for downloading. Eventually I will want to host the project on some space of my own and get a nice web interface for the mercurial repository going. I&#8217;ll have to find a new hosting company so it will take a while.</p>
<p>So that&#8217;s it, that&#8217;s what&#8217;s happened to the Dodger Level Editor over the last few months. I know I promised to make it public earlier but given the shape it was in at that time there really was no point. I want this to be at a point where people can actually almost use it before I make it public.</p>
<p>I know it&#8217;s been a while, and I know the few of you that actually care about this project have probably moved onto bigger and better things, but hopefully if you stick with me there will be something out soon.</p>
<div style="float:right;margin:0px 0px 0px 0px;"><a href="http://www.google.com/reader/link?url=http://www.learningpython.com/2008/06/22/level-editor-03-dodger/&title=Level Editor 0.3 (Dodger)&srcTitle=learning python&srcURL=http://www.learningpython.com"target="_blank" rel=""><img border="0" src="http://www.learningpython.com/wp-content/plugins/wp-google-buzz/icon/12.png" style="opacity:1;filter:alpha(opacity=100)" onmouseover="this.style.opacity=0.8;this.filters.alpha.opacity=70" onmouseout="this.style.opacity=1;this.filters.alpha.opacity=100"/> </a></div>]]></content:encoded>
			<wfw:commentRss>http://www.learningpython.com/2008/06/22/level-editor-03-dodger/feed/</wfw:commentRss>
		<slash:comments>17</slash:comments>
		</item>
	</channel>
</rss>
