<?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/"
	xmlns:media="http://search.yahoo.com/mrss/"
	>

<channel>
	<title>Quizzy Drop</title>
	<atom:link href="http://qzdrproject.wordpress.com/feed/" rel="self" type="application/rss+xml" />
	<link>http://qzdrproject.wordpress.com</link>
	<description>QZ's DrProject development blog</description>
	<lastBuildDate>Thu, 02 Jul 2009 01:20:54 +0000</lastBuildDate>
	<generator>http://wordpress.com/</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<cloud domain='qzdrproject.wordpress.com' port='80' path='/?rsscloud=notify' registerProcedure='' protocol='http-post' />
<image>
		<url>http://www.gravatar.com/blavatar/72ff8a69095038e3f12267bf4c8498b6?s=96&#038;d=http://s.wordpress.com/i/buttonw-com.png</url>
		<title>Quizzy Drop</title>
		<link>http://qzdrproject.wordpress.com</link>
	</image>
			<item>
		<title>Troubleshooting networking</title>
		<link>http://qzdrproject.wordpress.com/2008/08/27/troubleshooting-networking/</link>
		<comments>http://qzdrproject.wordpress.com/2008/08/27/troubleshooting-networking/#comments</comments>
		<pubDate>Wed, 27 Aug 2008 19:06:32 +0000</pubDate>
		<dc:creator>qztxon</dc:creator>
				<category><![CDATA[DrProject]]></category>
		<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://qzdrproject.wordpress.com/?p=89</guid>
		<description><![CDATA[a.k.a. I F***ING HATE COMPUTERS WHEN THEY DON&#8217;T WORK RIGHT AND I CAN&#8217;T FIX THEM
Introduction
Up until now, I&#8217;ve almost always been running the DrProject server and the web browser to drive it on the same machine. For reasons I will not go into, I needed to run DrProject on an Ubuntu Linux installation on one [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=qzdrproject.wordpress.com&blog=3765766&post=89&subd=qzdrproject&ref=&feed=1" />]]></description>
			<content:encoded><![CDATA[<div class='snap_preview'><br /><p><abbr title="also known as">a.k.a.</abbr> I F***ING HATE COMPUTERS WHEN THEY DON&#8217;T WORK RIGHT AND I CAN&#8217;T FIX THEM</p>
<p><strong>Introduction</strong></p>
<p>Up until now, I&#8217;ve almost always been running the DrProject server and the web browser to drive it on the same machine. For reasons I will not go into, I needed to run DrProject on an Ubuntu Linux installation on one computer and run the web browser on Windows on another computer. These two computers were on the same <abbr title="local-area network">LAN</abbr>. Let&#8217;s call these computers Lin and Win, respectively. Please don&#8217;t mind me personifying these machines.</p>
<p>When Firefox on Lin talked to the DrProject being hosted locally, everything worked fine. When Firefox on Win talked to the DrProject server on Lin, each page request took an excruciatingly long time to complete &#8212; something in the order of tens of seconds, rather than a second or two.</p>
<p>Coming up is a chronicle of following numerous false leads, running up and down the stairs, and diving into the depths of computing to debug problems at a low level. It unfolded over the course of about 3 hours, and is told in approximately chronological order.</p>
<p><strong>Sanity checks</strong></p>
<p>First, I tried accessing DrProject using Internet Explorer (on Win) to made sure that it wasn&#8217;t Firefox&#8217;s fault. Indeed, it wasn&#8217;t. Second, I tried accessing the server using a different Windows computer. Still no luck. I even tried using telnet<sup>[0]</sup> to access the <abbr title="Hypertext Transfer Protocol">HTTP</abbr> server, where I still received a much-delayed response.</p>
<p>The puzzling thing was that Lin had no delays in accessing Internet resources, nor <abbr title="local-area network">LAN</abbr> resources (e.g. <abbr title="Server Message Block">SMB</abbr> into the Windows boxes).</p>
<p>In retrospect, if Windows was the problem, then I wouldn&#8217;t have caught it because I didn&#8217;t have another Linux computer on hand.<sup>[1]</sup></p>
<p><strong>Networking</strong></p>
<p><a href="http://qzdrproject.files.wordpress.com/2008/08/smartlink-hub.jpg"><img class="alignright size-thumbnail wp-image-108" src="http://qzdrproject.files.wordpress.com/2008/08/smartlink-hub.jpg?w=110&#038;h=96" alt="" width="110" height="96" /></a>Maybe the network was to blame. All the computers in question were hooked up to a home router (&#8220;residential gateway&#8221;), and maybe it was causing problems. So I hooked up Lin and Win directly (on a single cable), and set up a static <abbr title="Internet Protocol">IP</abbr> configuration for each. Even after back-and-forth tweaking and checking, this didn&#8217;t work. So I produced my old 10 <abbr title="megabit per second">Mb/s</abbr> Ethernet hub, and connected these two computers to the hub. After more <abbr title="Internet Protocol">IP</abbr> configuration tweaking, I finally got these computers to talk to each other again.</p>
<p>Mind you, all of this was complicated by the fact that Lin and Win were located one floor apart (yay for running up and down the stairs). Also, Lin had 2 network interfaces<sup>[2]</sup>, and it was difficult to tell which one was mapped to device eth1 and which was mapped to eth2. I did try enabling and disabling each of these two interfaces.</p>
<p>&#8230; And there was no improvement in the Win-browser-talking-to-Lin-server lag.</p>
<p><strong>Enter Wireshark (formerly Ethereal)</strong></p>
<p><a href="http://qzdrproject.files.wordpress.com/2008/08/wireshark.png"><img class="alignright size-thumbnail wp-image-95" src="http://qzdrproject.files.wordpress.com/2008/08/wireshark.png?w=127&#038;h=96" alt="" width="127" height="96" /></a></p>
<p>By now, I had dragged my friend Roy into the problem, as he is a Linux expert and a competent programmer. Other than mildly disagreeing about my choice of screen capture software, he suggested right off the bat that I analyze the network traffic with Wireshark, a packet sniffer. Since I used the older Ethereal back on Windows, I promptly set off to install Wireshark through the Debian package system without hesitation.</p>
<p>In the meantime, I tested using Win to connect a server socket on Lin to see if that was a problem. Using telnet<sup>[3]</sup> on Win and a netcat listener<sup>[4]</sup> on Lin, I saw no delay at all. That was weird. More and more, it looked like &#8220;tracd&#8221;, the built-in <abbr title="Hypertext Transfer Protocol">HTTP</abbr> server in DrProject (inherited from Trac), was where I should have pointed my blame.</p>
<p>When Wireshark was downloaded and installed, I fired it up and captured the relevant network interface. I changed the DrProject server port from 8080 to the standard 80, and used the capture filter &#8220;tcp port http&#8221; to reduce the amount of data captured.</p>
<p>What immediately caught my eye was that while most rows were coloured green, quite a number of them were coloured black. Wireshark explained that the black rows represent packets whose <abbr title="Transmission Control Protocol">TCP</abbr> checksums were incorrect, giving the reason &#8216;maybe caused by &#8220;<abbr title="Transmission Control Protocol">TCP</abbr> checksum offload&#8221;?&#8217;.</p>
<p>Digging a bit deeper, these &#8220;black&#8221; packets were all from Lin to Win (but not all packets from Lin to Win were black), and they all had a size of 1514 bytes. But wait a minute! Isn&#8217;t it true that the Ethernet <abbr title="maximum transmission unit">MTU</abbr> is 1500 bytes? Wouldn&#8217;t it be bad to exceed the <abbr title="maximum transmission unit">MTU</abbr>? So I consulted <a href="http://en.wikipedia.org/wiki/Maximum_transmission_unit">Wikipedia</a> and <a href="http://tools.ietf.org/html/rfc1191"><abbr title="Request for Comments">RFC</abbr> 1191</a>, but to no avail. They confirmed that the Ethernet standard <abbr title="maximum transmission unit">MTU</abbr> is 1500 bytes, but didn&#8217;t mention whether that included Ethernet headers or not.</p>
<p><a href="http://qzdrproject.files.wordpress.com/2008/08/network-tools.png"><img class="alignright size-thumbnail wp-image-104" src="http://qzdrproject.files.wordpress.com/2008/08/network-tools.png?w=100&#038;h=96" alt="" width="100" height="96" /></a>Through Wireshark&#8217;s detailed analysis of the raw 1514 bytes of data, I concluded that the 14 bytes were for Ethernet headers &#8212; 6 bytes for the <abbr title="Media Access Control">MAC</abbr> address of the sending machine, 6 bytes for the <abbr title="Media Access Control">MAC</abbr> address of the receiving machine, and 2 bytes for the EtherType<sup>[5]</sup>. With a bit of ifconfig wizardry<sup>[6]</sup>, I set the <abbr title="maximum transmission unit">MTU</abbr> to 1486 bytes so that after adding the Ethernet headers, the total comes out to 1500 bytes. But I still had no luck with the slow connection problem!</p>
<p>Following the <abbr title="Transmission Control Protocol">TCP</abbr> conversations through Wireshark did not prove of much use either. But I did see that it took about 10 seconds to respond to each <abbr title="Hypertext Transfer Protocol">HTTP</abbr> connection.</p>
<p><strong>strace</strong></p>
<p><a href="http://qzdrproject.files.wordpress.com/2008/08/strace.png"><img class="alignright size-thumbnail wp-image-101" src="http://qzdrproject.files.wordpress.com/2008/08/strace.png?w=126&#038;h=96" alt="" width="126" height="96" /></a>Besides Wireshark, the other major recommendation from Roy was to run the DrProject server under strace. This program invokes another program, and traces (prints) all of the Unix system calls that the child program makes.</p>
<p>Roy asked me to inform him of the last line printed by strace whenever the output stopped momentarily. I first noted that the trace stopped at &#8220;wait4(-1,&#8221; after starting the server. He said that it was because the target process was launching a child process.</p>
<p>I realized that to make this trace work, I had to disable DrProject&#8217;s auto-reloader. Which actually required me to hack the code, because it seemed the &#8220;&#8211;auto-reload&#8221; command line option was not parsed and handled correctly. In addition to that, the Python BaseHTTPServer was multi-threaded, so I had to invoke strace with the -f option, which resulted in significantly more trace output to the screen.</p>
<p>Finally, something interesting appeared. When Win talks to Lin, the trace stops at &#8220;read(4,&#8221; for a number of seconds, then resumes. Roy said that 4 is the file descriptor, and asked me to trace all the actions starting from the point where that particular <abbr title="file descriptor">FD</abbr> (#4) was opened. This is what I found, with some irrelevant information removed:</p>
<pre>socket(PF_FILE, SOCK_STREAM, 0) = 4
fcntrl(4, F_GETFD)
connect(4, {sa_family=AF_FILE, path="/var/run/avahi-daemon/socket"}, 110) = 0
lseek(4, 0, SEEK_CUR) = -1 ESPIPE (Illegal seek)
write(4, "RESOLVE-ADDRESS 192.168.0.108\n", 30) = 30
read(4,  &lt;-- Hangs here for a few seconds</pre>
<p>If you ask me, that data being passed to the write system call looked like a <abbr title="Domain Name System">DNS</abbr> thing, or perhaps an <abbr title="Address Resolution Protocol">ARP</abbr> thing.</p>
<p><strong>Avahi</strong></p>
<p>With the evidence provided by strace in hand, Roy pointed to the Avahi Zeroconf software as the source of the problem. He asked me to toggle it &#8212; that is, start it if it was not running, and stop it if it was already running.</p>
<p>Stopping Avahi<sup>[7]</sup> and trying to access DrProject server on Lin from Win&#8217;s Firefox again&#8230; Success! W00t! 3 hours of intense troubleshooting had finally come to an end.</p>
<p><strong>Conclusion</strong></p>
<p>Was there a point in writing this? I don&#8217;t know. I don&#8217;t think you, the reader, can learn much from it. This article is comparable to a rant, with a hodge-podge of disconnected personal events and ideas. An honest and objective rant, though.</p>
<p>But I think this paints a picture of what computer problems look like, and how they are exhaustively troubleshooted and (hopefully) finally solved.</p>
<p>Oh yeah, and I took up about 1.5 hours of Roy&#8217;s time while he was at work. He has a flexible schedule as a software developer at a big company, so no worries. =P</p>
<p><strong>Footnotes</strong></p>
<p>Lin had the <abbr title="Internet Protocol">IP</abbr> address 192.168.0.101.</p>
<p>Win had the <abbr title="Internet Protocol">IP</abbr> address 192.168.0.108.</p>
<p>After Lin and Win could talk to each other, I would sit at Lin&#8217;s console and operate Lin while also hacking into Win using Remote Desktop Connection. So I didn&#8217;t run up and down between computers <em>that</em> much.</p>
<p>[0]: telnet 192.168.0.101 8000. Type &#8220;GET / HTTP/1.1 \r\n Host: 192.168.0.101 \r\n \r\n&#8221;.</p>
<p>[1]: Then again, I could have booted Ubuntu from a live <abbr title="Compact Disc">CD</abbr>.</p>
<p>[2]: One integrated on the motherboard, and one on a <abbr title="Peripheral Component Interconnect">PCI</abbr> card.</p>
<p>[3]: telnet 192.168.0.101 8000</p>
<p>[4]: netcat -l -p 8000</p>
<p>[5]: In this case, it was 0&#215;0800 for <abbr title="Internet Protocol version 4">IPv4</abbr>.</p>
<p>[6]: ifconfig eth2 mtu 1486</p>
<p>[7]: sudo /etc/init.d/avahi-daemon stop</p>
<img alt="" border="0" src="http://feeds.wordpress.com/1.0/categories/qzdrproject.wordpress.com/89/" /> <img alt="" border="0" src="http://feeds.wordpress.com/1.0/tags/qzdrproject.wordpress.com/89/" /> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/qzdrproject.wordpress.com/89/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/qzdrproject.wordpress.com/89/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/qzdrproject.wordpress.com/89/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/qzdrproject.wordpress.com/89/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/qzdrproject.wordpress.com/89/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/qzdrproject.wordpress.com/89/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/qzdrproject.wordpress.com/89/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/qzdrproject.wordpress.com/89/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/qzdrproject.wordpress.com/89/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/qzdrproject.wordpress.com/89/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=qzdrproject.wordpress.com&blog=3765766&post=89&subd=qzdrproject&ref=&feed=1" /></div>]]></content:encoded>
			<wfw:commentRss>http://qzdrproject.wordpress.com/2008/08/27/troubleshooting-networking/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="" medium="image">
			<media:title type="html">qztxon</media:title>
		</media:content>

		<media:content url="http://qzdrproject.files.wordpress.com/2008/08/smartlink-hub.jpg?w=110" medium="image" />

		<media:content url="http://qzdrproject.files.wordpress.com/2008/08/wireshark.png?w=127" medium="image" />

		<media:content url="http://qzdrproject.files.wordpress.com/2008/08/network-tools.png?w=100" medium="image" />

		<media:content url="http://qzdrproject.files.wordpress.com/2008/08/strace.png?w=126" medium="image" />
	</item>
		<item>
		<title>Simplified admin menu and enhanced users/projects pages</title>
		<link>http://qzdrproject.wordpress.com/2008/08/08/simplified-admin-menu-and-enhanced-usersprojects-pages/</link>
		<comments>http://qzdrproject.wordpress.com/2008/08/08/simplified-admin-menu-and-enhanced-usersprojects-pages/#comments</comments>
		<pubDate>Fri, 08 Aug 2008 18:25:50 +0000</pubDate>
		<dc:creator>qztxon</dc:creator>
				<category><![CDATA[DrProject]]></category>
		<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://qzdrproject.wordpress.com/?p=81</guid>
		<description><![CDATA[As per Liz&#8217;s suggestions (#0, #1, #2), I have simplifed the admin menu, and added statuses and actions to the list users page and the list projects pages. (Implemented in changeset 5663.) Screenshots:
The reduced admin menu:

Manage Users page:

Manage Projects page:

Manage Roles and Capabilities page:

       <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=qzdrproject.wordpress.com&blog=3765766&post=81&subd=qzdrproject&ref=&feed=1" />]]></description>
			<content:encoded><![CDATA[<div class='snap_preview'><br /><p>As per Liz&#8217;s suggestions (<a href="http://www.lizblankenship.com/drproject/admin_panelv5/Admin_menu.html">#0</a>, <a href="http://www.lizblankenship.com/drproject/admin_panelv5/Users.html">#1</a>, <a href="http://www.lizblankenship.com/drproject/admin_panelv5/Projects.html">#2</a>), I have simplifed the admin menu, and added statuses and actions to the list users page and the list projects pages. (Implemented in changeset 5663.) Screenshots:</p>
<p>The reduced admin menu:</p>
<p><a href="http://qzdrproject.files.wordpress.com/2008/08/admin-menu.png"><img class="alignnone size-medium wp-image-82" src="http://qzdrproject.files.wordpress.com/2008/08/admin-menu.png?w=212&#038;h=171" alt="" width="212" height="171" /></a></p>
<p>Manage Users page:</p>
<p><a href="http://qzdrproject.files.wordpress.com/2008/08/manage-users.png"><img class="alignnone size-medium wp-image-83" src="http://qzdrproject.files.wordpress.com/2008/08/manage-users.png?w=183&#038;h=300" alt="" width="183" height="300" /></a></p>
<p>Manage Projects page:</p>
<p><a href="http://qzdrproject.files.wordpress.com/2008/08/manage-projects.png"><img class="alignnone size-medium wp-image-84" src="http://qzdrproject.files.wordpress.com/2008/08/manage-projects.png?w=300&#038;h=192" alt="" width="300" height="192" /></a></p>
<p>Manage Roles and Capabilities page:</p>
<p><a href="http://qzdrproject.files.wordpress.com/2008/08/manage-roles-and-capabilities.png"><img class="alignnone size-medium wp-image-85" src="http://qzdrproject.files.wordpress.com/2008/08/manage-roles-and-capabilities.png?w=300&#038;h=294" alt="" width="300" height="294" /></a></p>
<img alt="" border="0" src="http://feeds.wordpress.com/1.0/categories/qzdrproject.wordpress.com/81/" /> <img alt="" border="0" src="http://feeds.wordpress.com/1.0/tags/qzdrproject.wordpress.com/81/" /> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/qzdrproject.wordpress.com/81/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/qzdrproject.wordpress.com/81/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/qzdrproject.wordpress.com/81/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/qzdrproject.wordpress.com/81/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/qzdrproject.wordpress.com/81/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/qzdrproject.wordpress.com/81/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/qzdrproject.wordpress.com/81/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/qzdrproject.wordpress.com/81/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/qzdrproject.wordpress.com/81/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/qzdrproject.wordpress.com/81/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=qzdrproject.wordpress.com&blog=3765766&post=81&subd=qzdrproject&ref=&feed=1" /></div>]]></content:encoded>
			<wfw:commentRss>http://qzdrproject.wordpress.com/2008/08/08/simplified-admin-menu-and-enhanced-usersprojects-pages/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="" medium="image">
			<media:title type="html">qztxon</media:title>
		</media:content>

		<media:content url="http://qzdrproject.files.wordpress.com/2008/08/admin-menu.png?w=212" medium="image" />

		<media:content url="http://qzdrproject.files.wordpress.com/2008/08/manage-users.png?w=183" medium="image" />

		<media:content url="http://qzdrproject.files.wordpress.com/2008/08/manage-projects.png?w=300" medium="image" />

		<media:content url="http://qzdrproject.files.wordpress.com/2008/08/manage-roles-and-capabilities.png?w=300" medium="image" />
	</item>
		<item>
		<title>Easy examples of redundancy</title>
		<link>http://qzdrproject.wordpress.com/2008/07/29/easy-examples-of-redundancy/</link>
		<comments>http://qzdrproject.wordpress.com/2008/07/29/easy-examples-of-redundancy/#comments</comments>
		<pubDate>Tue, 29 Jul 2008 19:30:25 +0000</pubDate>
		<dc:creator>qztxon</dc:creator>
				<category><![CDATA[Python]]></category>
		<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://qzdrproject.wordpress.com/?p=71</guid>
		<description><![CDATA[The following are some examples of simple redundancies in procedural programming. They are given in Python. I typically run into these when I simplify my code after writing it for the first time or after making edits.
Using if-else to assign a Boolean:
if condition:
    x = True
else:
    x = False
Simplified:
x [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=qzdrproject.wordpress.com&blog=3765766&post=71&subd=qzdrproject&ref=&feed=1" />]]></description>
			<content:encoded><![CDATA[<div class='snap_preview'><br /><p>The following are some examples of simple redundancies in procedural programming. They are given in Python. I typically run into these when I simplify my code after writing it for the first time or after making edits.</p>
<p><strong>Using if-else to assign a Boolean:</strong></p>
<pre>if <var>condition</var>:
    x = True
else:
    x = False</pre>
<p>Simplified:</p>
<pre>x = <var>condition</var></pre>
<p>(Requires that <var>condition</var> is a Boolean.)</p>
<p><strong>Returning immediately after an assignment:</strong></p>
<pre>y = <var>value</var>
return y</pre>
<p>Simplified:</p>
<pre>return <var>value</var></pre>
<p><strong>Common code among branches:</strong></p>
<pre>if <var>condition</var>:
    <var>group of statements A</var>
    <var>group of statements B</var>
    <var>group of statements D</var>
else:
    <var>group of statements A</var>
    <var>group of statements C</var>
    <var>group of statements D</var></pre>
<p>Simplified:</p>
<pre><var>group of statements A</var>
if <var>condition</var>:
    <var>group of statements B</var>
else:
    <var>group of statements C</var>
<var>group of statements D</var></pre>
<p><strong>Nested if-statements:</strong></p>
<pre>if <var>condition0</var>:
    if<var> condition1</var>:
        <var>statements</var></pre>
<p>Simplified:</p>
<pre>if <var>condition0</var> and <var>condition1</var>:
    <var>statements</var></pre>
<p>Requires that the outer if-statement does not have an else-clause.</p>
<p><strong>If-statements with the same actions:</strong></p>
<pre>if <var>condition0</var>:
    <var>statements (same)</var>
if <var>condition1</var>:
    <var>statements (same)</var></pre>
<p>Simplified:</p>
<pre>if <var>condition0</var> or <var>condition1</var>:
    <var>statements (same)</var></pre>
<p>Requires <var>condition0</var> and <var>condition1</var> to be disjoint, or <var>statements</pre>
<p> to be idempotent.</p>
<img alt="" border="0" src="http://feeds.wordpress.com/1.0/categories/qzdrproject.wordpress.com/71/" /> <img alt="" border="0" src="http://feeds.wordpress.com/1.0/tags/qzdrproject.wordpress.com/71/" /> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/qzdrproject.wordpress.com/71/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/qzdrproject.wordpress.com/71/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/qzdrproject.wordpress.com/71/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/qzdrproject.wordpress.com/71/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/qzdrproject.wordpress.com/71/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/qzdrproject.wordpress.com/71/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/qzdrproject.wordpress.com/71/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/qzdrproject.wordpress.com/71/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/qzdrproject.wordpress.com/71/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/qzdrproject.wordpress.com/71/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=qzdrproject.wordpress.com&blog=3765766&post=71&subd=qzdrproject&ref=&feed=1" /></div>]]></content:encoded>
			<wfw:commentRss>http://qzdrproject.wordpress.com/2008/07/29/easy-examples-of-redundancy/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
	
		<media:content url="" medium="image">
			<media:title type="html">qztxon</media:title>
		</media:content>
	</item>
		<item>
		<title>Department of redundancy department: Python lambdas</title>
		<link>http://qzdrproject.wordpress.com/2008/07/29/department-of-redundancy-department-python-lambdas/</link>
		<comments>http://qzdrproject.wordpress.com/2008/07/29/department-of-redundancy-department-python-lambdas/#comments</comments>
		<pubDate>Tue, 29 Jul 2008 16:42:47 +0000</pubDate>
		<dc:creator>qztxon</dc:creator>
				<category><![CDATA[DrProject]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://qzdrproject.wordpress.com/?p=69</guid>
		<description><![CDATA[A coworker recently pointed out the lambda (anonymous function) in this piece of code that I wrote was redundant:
project_key_regex = re.compile(r"^project(\d+)$")
for key in filter(lambda k: project_key_regex.match(k), req.args.keys()):
    ...

It would be improved like this:
project_key_regex = re.compile(r"^project(\d+)$")
for key in filter(project_key_regex.match, req.args.keys()):
    ...
Apparently, methods of an object can be thought of as [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=qzdrproject.wordpress.com&blog=3765766&post=69&subd=qzdrproject&ref=&feed=1" />]]></description>
			<content:encoded><![CDATA[<div class='snap_preview'><br /><p>A coworker recently pointed out the lambda (anonymous function) in this piece of code that I wrote was redundant:</p>
<pre><code>project_key_regex = re.compile(r"^project(\d+)$")
for key in filter(lambda k: project_key_regex.match(k), req.args.keys()):
    ...
</code></pre>
<p>It would be improved like this:</p>
<pre><code>project_key_regex = re.compile(r"^project(\d+)$")
for key in filter(project_key_regex.match, req.args.keys()):
    ...</code></pre>
<p>Apparently, methods of an object can be thought of as functions that have one variable bound to the object.</p>
<p>A bit of info about the phrase &#8220;Department of Redundancy Department&#8221; on Everything2: <a href="http://everything2.com/title/Department%2520of%2520Redundancy%2520Department">http://everything2.com/title/Department%2520of%2520Redundancy%2520Department</a></p>
<img alt="" border="0" src="http://feeds.wordpress.com/1.0/categories/qzdrproject.wordpress.com/69/" /> <img alt="" border="0" src="http://feeds.wordpress.com/1.0/tags/qzdrproject.wordpress.com/69/" /> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/qzdrproject.wordpress.com/69/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/qzdrproject.wordpress.com/69/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/qzdrproject.wordpress.com/69/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/qzdrproject.wordpress.com/69/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/qzdrproject.wordpress.com/69/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/qzdrproject.wordpress.com/69/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/qzdrproject.wordpress.com/69/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/qzdrproject.wordpress.com/69/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/qzdrproject.wordpress.com/69/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/qzdrproject.wordpress.com/69/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=qzdrproject.wordpress.com&blog=3765766&post=69&subd=qzdrproject&ref=&feed=1" /></div>]]></content:encoded>
			<wfw:commentRss>http://qzdrproject.wordpress.com/2008/07/29/department-of-redundancy-department-python-lambdas/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="" medium="image">
			<media:title type="html">qztxon</media:title>
		</media:content>
	</item>
		<item>
		<title>The revised create users and create projects doublet</title>
		<link>http://qzdrproject.wordpress.com/2008/07/28/the-revised-create-users-and-create-projects-doublet/</link>
		<comments>http://qzdrproject.wordpress.com/2008/07/28/the-revised-create-users-and-create-projects-doublet/#comments</comments>
		<pubDate>Mon, 28 Jul 2008 15:15:05 +0000</pubDate>
		<dc:creator>qztxon</dc:creator>
				<category><![CDATA[DrProject]]></category>
		<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://qzdrproject.wordpress.com/?p=62</guid>
		<description><![CDATA[A picture is worth a few hundred thousand bytes, so without further ado, this is what&#8217;s new:


Although it isn&#8217;t apparent from the screenshot, a new memberships row (with &#8220;select a user/project&#8221; and &#8220;select a role&#8221;) is added whenever the final row is filled.
Compare these to the interfaces that we had before:


     [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=qzdrproject.wordpress.com&blog=3765766&post=62&subd=qzdrproject&ref=&feed=1" />]]></description>
			<content:encoded><![CDATA[<div class='snap_preview'><br /><p>A picture is worth a few hundred thousand bytes, so without further ado, this is what&#8217;s new:</p>
<p><a href="http://qzdrproject.files.wordpress.com/2008/07/create-users.png"><img class="alignnone size-medium wp-image-60" src="http://qzdrproject.files.wordpress.com/2008/07/create-users.png?w=300&#038;h=250" alt="" width="300" height="250" /></a></p>
<p><a href="http://qzdrproject.files.wordpress.com/2008/07/create-projects.png"><img class="alignnone size-medium wp-image-61" src="http://qzdrproject.files.wordpress.com/2008/07/create-projects.png?w=300&#038;h=201" alt="" width="300" height="201" /></a></p>
<p>Although it isn&#8217;t apparent from the screenshot, a new memberships row (with &#8220;select a user/project&#8221; and &#8220;select a role&#8221;) is added whenever the final row is filled.</p>
<p>Compare these to the interfaces that we had before:</p>
<p><a href="http://qzdrproject.files.wordpress.com/2008/07/old-create-new-users.png"><img class="alignnone size-medium wp-image-65" src="http://qzdrproject.files.wordpress.com/2008/07/old-create-new-users.png?w=300&#038;h=142" alt="" width="300" height="142" /></a></p>
<p><a href="http://qzdrproject.files.wordpress.com/2008/07/old-create-new-projects.png"><img class="alignnone size-medium wp-image-66" src="http://qzdrproject.files.wordpress.com/2008/07/old-create-new-projects.png?w=300&#038;h=179" alt="" width="300" height="179" /></a></p>
<img alt="" border="0" src="http://feeds.wordpress.com/1.0/categories/qzdrproject.wordpress.com/62/" /> <img alt="" border="0" src="http://feeds.wordpress.com/1.0/tags/qzdrproject.wordpress.com/62/" /> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/qzdrproject.wordpress.com/62/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/qzdrproject.wordpress.com/62/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/qzdrproject.wordpress.com/62/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/qzdrproject.wordpress.com/62/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/qzdrproject.wordpress.com/62/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/qzdrproject.wordpress.com/62/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/qzdrproject.wordpress.com/62/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/qzdrproject.wordpress.com/62/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/qzdrproject.wordpress.com/62/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/qzdrproject.wordpress.com/62/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=qzdrproject.wordpress.com&blog=3765766&post=62&subd=qzdrproject&ref=&feed=1" /></div>]]></content:encoded>
			<wfw:commentRss>http://qzdrproject.wordpress.com/2008/07/28/the-revised-create-users-and-create-projects-doublet/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
	
		<media:content url="" medium="image">
			<media:title type="html">qztxon</media:title>
		</media:content>

		<media:content url="http://qzdrproject.files.wordpress.com/2008/07/create-users.png?w=300" medium="image" />

		<media:content url="http://qzdrproject.files.wordpress.com/2008/07/create-projects.png?w=300" medium="image" />

		<media:content url="http://qzdrproject.files.wordpress.com/2008/07/old-create-new-users.png?w=300" medium="image" />

		<media:content url="http://qzdrproject.files.wordpress.com/2008/07/old-create-new-projects.png?w=300" medium="image" />
	</item>
		<item>
		<title>Create Multiple Users: Error handling</title>
		<link>http://qzdrproject.wordpress.com/2008/07/23/create-multiple-users-error-handling/</link>
		<comments>http://qzdrproject.wordpress.com/2008/07/23/create-multiple-users-error-handling/#comments</comments>
		<pubDate>Thu, 24 Jul 2008 01:09:15 +0000</pubDate>
		<dc:creator>qztxon</dc:creator>
				<category><![CDATA[DrProject]]></category>
		<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://qzdrproject.wordpress.com/?p=56</guid>
		<description><![CDATA[The new Create Multiple Users page has a back-end that gives information on all sorts of errors:

       <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=qzdrproject.wordpress.com&blog=3765766&post=56&subd=qzdrproject&ref=&feed=1" />]]></description>
			<content:encoded><![CDATA[<div class='snap_preview'><br /><p>The new Create Multiple Users page has a back-end that gives information on all sorts of errors:</p>
<p><a href="http://qzdrproject.files.wordpress.com/2008/07/create-multiple-users-error-handling.png"><img class="alignnone size-medium wp-image-57" src="http://qzdrproject.files.wordpress.com/2008/07/create-multiple-users-error-handling.png?w=300&#038;h=229" alt="" width="300" height="229" /></a></p>
<img alt="" border="0" src="http://feeds.wordpress.com/1.0/categories/qzdrproject.wordpress.com/56/" /> <img alt="" border="0" src="http://feeds.wordpress.com/1.0/tags/qzdrproject.wordpress.com/56/" /> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/qzdrproject.wordpress.com/56/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/qzdrproject.wordpress.com/56/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/qzdrproject.wordpress.com/56/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/qzdrproject.wordpress.com/56/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/qzdrproject.wordpress.com/56/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/qzdrproject.wordpress.com/56/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/qzdrproject.wordpress.com/56/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/qzdrproject.wordpress.com/56/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/qzdrproject.wordpress.com/56/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/qzdrproject.wordpress.com/56/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=qzdrproject.wordpress.com&blog=3765766&post=56&subd=qzdrproject&ref=&feed=1" /></div>]]></content:encoded>
			<wfw:commentRss>http://qzdrproject.wordpress.com/2008/07/23/create-multiple-users-error-handling/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
	
		<media:content url="" medium="image">
			<media:title type="html">qztxon</media:title>
		</media:content>

		<media:content url="http://qzdrproject.files.wordpress.com/2008/07/create-multiple-users-error-handling.png?w=300" medium="image" />
	</item>
		<item>
		<title>Great bug writers think alike</title>
		<link>http://qzdrproject.wordpress.com/2008/07/10/great-bug-writers-think-alike/</link>
		<comments>http://qzdrproject.wordpress.com/2008/07/10/great-bug-writers-think-alike/#comments</comments>
		<pubDate>Thu, 10 Jul 2008 14:58:09 +0000</pubDate>
		<dc:creator>qztxon</dc:creator>
				<category><![CDATA[DrProject]]></category>
		<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://qzdrproject.wordpress.com/?p=50</guid>
		<description><![CDATA[a.k.a. &#8220;A subtle bug from a perfect storm of HTTP, HTML, JavaScript, and DOM&#8220;
My current work
I&#8217;m currently in the midst of implementing a new interface for creating new users. This is how it currently looks like:

The project membership table is created on the client side using JavaScript. The administrator adds and removes memberships (rows) without [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=qzdrproject.wordpress.com&blog=3765766&post=50&subd=qzdrproject&ref=&feed=1" />]]></description>
			<content:encoded><![CDATA[<div class='snap_preview'><br /><p><abbr title="also known as">a.k.a.</abbr> &#8220;A subtle bug from a perfect storm of <abbr title="Hypertext Transfer Protocol">HTTP</abbr>, <abbr title="Hypertext Markup Language">HTML</abbr>, JavaScript, and <abbr title="Document Object Model">DOM</abbr>&#8220;</p>
<p><strong>My current work</strong></p>
<p>I&#8217;m currently in the midst of implementing a new interface for creating new users. This is how it currently looks like:</p>
<p><a href="http://qzdrproject.files.wordpress.com/2008/07/create-new-users.png"><img class="alignnone size-medium wp-image-51" src="http://qzdrproject.files.wordpress.com/2008/07/create-new-users.png?w=300&#038;h=229" alt="" width="300" height="229" /></a></p>
<p>The project membership table is created on the client side using JavaScript. The administrator adds and removes memberships (rows) without submitting the form.</p>
<p><strong>HTML forms and HTTP, revisited</strong></p>
<p>(Recall <a href="http://qzdrproject.wordpress.com/2008/06/22/a-simplified-overview-of-html-forms/">A simplified overview of HTML forms</a>.) When the form is submitted over HTTP, all that is sent is a <a href="http://en.wikipedia.org/wiki/Associative_array">dictionary</a> of key-value pairs. Each form element (text box, checkbox, select, etc.) generates at most one item for the dictionary, where the key is the name of the element (given by the name attribute) and the value is the string value of the element (&#8220;alice&#8221;, &#8220;pA55w0rd&#8221;, &#8220;on&#8221;, &#8220;viewer&#8221;, etc.).</p>
<p>Perhaps surprisingly, the dictionary&#8217;s keys need not be unique. For example, if there are two text boxes named &#8220;foo&#8221;, one with the value &#8220;bar&#8221; and one with the value &#8220;baz&#8221;, then the submitted form data would be &#8220;foo=bar, foo=baz&#8221; (or possibly &#8220;foo=baz, foo=bar&#8221;).</p>
<p><strong>The tricky stuff: Client side</strong></p>
<p>So for the form pictured above, the submitted information will be something along the lines of &#8220;username=roule, email=roulette@localhost, realname=Roulette, affiliation=Pani, password=01234567&#8243;&#8230; But wait! What about the membership table?</p>
<p>The first (but incorrect) idea that comes to mind is to give the same name for all elements in a column. For example, all the project selects would be named &#8220;project&#8221;, and all the role selects would be named &#8220;role&#8221;. The problem with this is that in the presence of multiple &#8220;project&#8221; and &#8220;role&#8221; keys, we don&#8217;t know which one was assoicated with which. A concrete example: Suppose John is a viewer in Alpha and a developer in Beta. The submitted form data would look like &#8220;project=Alpha, project=Beta, role=viewer, role=developer&#8221;, but with the entries being presented to the server in an <em>arbitrary</em> order. So it would be impossible to associate projects and roles uniquely.</p>
<p>Clearly then, the solution is to give each field a unique name. A simple method is to add a counter after the name – like &#8220;project0&#8243;, &#8220;project1&#8243;, &#8220;role0&#8243;, &#8220;role1&#8243;, etc.</p>
<p><strong>The tricky stuff: Server side</strong></p>
<p>How would the server process this information when it&#8217;s submitted? Assume that the client does not send the count of the number of rows. One way for the server to handle the variable number of rows is to start from a prearranged fixed number – 0 in this example – and process form fields and count upwards until the first <var>n</var> such that the submitted field &#8220;project<var>n</var>&#8221; does not exist.</p>
<p>So far so good, right? But notice that on the client side, membership rows can be removed. Suppose that for simplicity, we don&#8217;t re-enumerate the remaining form fields. So if we had &#8220;project0&#8243;, &#8220;project1&#8243;, &#8220;project2&#8243; and then removed the middle entry, then we&#8217;d be left with &#8220;project0&#8243; and &#8220;project2&#8243;. Clearly, this interacts badly with the server side handler just described, since &#8220;project2&#8243; will be ignored. (Because &#8220;project1&#8243; does not exist, the server stops processing.)</p>
<p><strong>Solutions</strong></p>
<p>There are two relatively simple solutions to this problem:</p>
<ul>
<li>Keep the client-side behaviour and modify the server-side behaviour. For each new row, give an auto-incrementing numerical suffix for the form fields. Do nothing special when removing rows. On the server, iterate through all form fields that have a name of the form &#8220;project<var>N</var>&#8220;, where <var>N</var> is a number string. Ignore &#8220;gaps&#8221; in the numbering.</li>
<li>Modify the client-side behaviour and keep the server-side behaviour. When a row is removed, re-enumerate the rows that follow it. This is the solution that I picked, for no particular strong reason.</li>
</ul>
<p><strong>Great bug writers think alike</strong></p>
<p>Now, if this problem were merely hypothetical, I wouldn&#8217;t have a good reason to write this rant-like-lengthed post about it. But it does already exist in DrProject! Namely, it manifests itself in the &#8220;Membership Preferences&#8221; section of the Edit User page and also on the current user&#8217;s Preferences page.</p>
<p>The offending server-side form handler code is found in <a href="https://www.drproject.org/DrProject/browser/trunk/drproject?file=register.py#L88">register.py</a>. (The complicated process of pinpointing this piece of code will be another story.)</p>
<img alt="" border="0" src="http://feeds.wordpress.com/1.0/categories/qzdrproject.wordpress.com/50/" /> <img alt="" border="0" src="http://feeds.wordpress.com/1.0/tags/qzdrproject.wordpress.com/50/" /> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/qzdrproject.wordpress.com/50/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/qzdrproject.wordpress.com/50/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/qzdrproject.wordpress.com/50/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/qzdrproject.wordpress.com/50/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/qzdrproject.wordpress.com/50/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/qzdrproject.wordpress.com/50/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/qzdrproject.wordpress.com/50/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/qzdrproject.wordpress.com/50/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/qzdrproject.wordpress.com/50/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/qzdrproject.wordpress.com/50/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=qzdrproject.wordpress.com&blog=3765766&post=50&subd=qzdrproject&ref=&feed=1" /></div>]]></content:encoded>
			<wfw:commentRss>http://qzdrproject.wordpress.com/2008/07/10/great-bug-writers-think-alike/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
	
		<media:content url="" medium="image">
			<media:title type="html">qztxon</media:title>
		</media:content>

		<media:content url="http://qzdrproject.files.wordpress.com/2008/07/create-new-users.png?w=300" medium="image" />
	</item>
		<item>
		<title>Final role editor (for now)</title>
		<link>http://qzdrproject.wordpress.com/2008/07/09/final-role-editor-for-now/</link>
		<comments>http://qzdrproject.wordpress.com/2008/07/09/final-role-editor-for-now/#comments</comments>
		<pubDate>Wed, 09 Jul 2008 14:55:09 +0000</pubDate>
		<dc:creator>qztxon</dc:creator>
				<category><![CDATA[DrProject]]></category>
		<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://qzdrproject.wordpress.com/?p=42</guid>
		<description><![CDATA[This is the current state of the role editor. Development on it has wrapped up a few days ago. It is available at (SVN) https://drproject.org/svn/drproject/DrProject/branches/newadmin.
Initial screen:

Adding a role:

Role added:

Editing a role (click on pencil and paper icon):

Done editing a role:

Removing a role that is still in use (click red X, get redirected to this page):

Note [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=qzdrproject.wordpress.com&blog=3765766&post=42&subd=qzdrproject&ref=&feed=1" />]]></description>
			<content:encoded><![CDATA[<div class='snap_preview'><br /><p>This is the current state of the role editor. Development on it has wrapped up a few days ago. It is available at (<abbr title="Subversion">SVN</abbr>) <a href="https://drproject.org/svn/drproject/DrProject/branches/newadmin">https://drproject.org/svn/drproject/DrProject/branches/newadmin</a>.</p>
<p>Initial screen:</p>
<p><a href="http://qzdrproject.files.wordpress.com/2008/07/0.png"><img class="alignnone size-medium wp-image-43" src="http://qzdrproject.files.wordpress.com/2008/07/0.png?w=300&#038;h=293" alt="" width="300" height="293" /></a></p>
<p>Adding a role:</p>
<p><a href="http://qzdrproject.files.wordpress.com/2008/07/1.png"><img class="alignnone size-medium wp-image-44" src="http://qzdrproject.files.wordpress.com/2008/07/1.png?w=300&#038;h=293" alt="" width="300" height="293" /></a></p>
<p>Role added:</p>
<p><a href="http://qzdrproject.files.wordpress.com/2008/07/2.png"><img class="alignnone size-medium wp-image-45" src="http://qzdrproject.files.wordpress.com/2008/07/2.png?w=293&#038;h=300" alt="" width="293" height="300" /></a></p>
<p>Editing a role (click on pencil and paper icon):</p>
<p><a href="http://qzdrproject.files.wordpress.com/2008/07/3.png"><img class="alignnone size-medium wp-image-46" src="http://qzdrproject.files.wordpress.com/2008/07/3.png?w=290&#038;h=300" alt="" width="290" height="300" /></a></p>
<p>Done editing a role:</p>
<p><a href="http://qzdrproject.files.wordpress.com/2008/07/4.png"><img class="alignnone size-medium wp-image-47" src="http://qzdrproject.files.wordpress.com/2008/07/4.png?w=293&#038;h=300" alt="" width="293" height="300" /></a></p>
<p>Removing a role that is still in use (click red X, get redirected to this page):</p>
<p><a href="http://qzdrproject.files.wordpress.com/2008/07/5.png"><img class="alignnone size-medium wp-image-48" src="http://qzdrproject.files.wordpress.com/2008/07/5.png?w=300&#038;h=229" alt="" width="300" height="229" /></a></p>
<p>Note that this role editor is AJAX-powered. The actions of adding, editing, and removing a role are immediately performed on the server, but do not incur page reloads on the client.</p>
<img alt="" border="0" src="http://feeds.wordpress.com/1.0/categories/qzdrproject.wordpress.com/42/" /> <img alt="" border="0" src="http://feeds.wordpress.com/1.0/tags/qzdrproject.wordpress.com/42/" /> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/qzdrproject.wordpress.com/42/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/qzdrproject.wordpress.com/42/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/qzdrproject.wordpress.com/42/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/qzdrproject.wordpress.com/42/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/qzdrproject.wordpress.com/42/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/qzdrproject.wordpress.com/42/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/qzdrproject.wordpress.com/42/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/qzdrproject.wordpress.com/42/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/qzdrproject.wordpress.com/42/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/qzdrproject.wordpress.com/42/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=qzdrproject.wordpress.com&blog=3765766&post=42&subd=qzdrproject&ref=&feed=1" /></div>]]></content:encoded>
			<wfw:commentRss>http://qzdrproject.wordpress.com/2008/07/09/final-role-editor-for-now/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
	
		<media:content url="" medium="image">
			<media:title type="html">qztxon</media:title>
		</media:content>

		<media:content url="http://qzdrproject.files.wordpress.com/2008/07/0.png?w=300" medium="image" />

		<media:content url="http://qzdrproject.files.wordpress.com/2008/07/1.png?w=300" medium="image" />

		<media:content url="http://qzdrproject.files.wordpress.com/2008/07/2.png?w=293" medium="image" />

		<media:content url="http://qzdrproject.files.wordpress.com/2008/07/3.png?w=290" medium="image" />

		<media:content url="http://qzdrproject.files.wordpress.com/2008/07/4.png?w=293" medium="image" />

		<media:content url="http://qzdrproject.files.wordpress.com/2008/07/5.png?w=300" medium="image" />
	</item>
		<item>
		<title>Dumb redirects interact poorly with forms</title>
		<link>http://qzdrproject.wordpress.com/2008/06/23/dumb-redirects-interact-poorly-with-forms/</link>
		<comments>http://qzdrproject.wordpress.com/2008/06/23/dumb-redirects-interact-poorly-with-forms/#comments</comments>
		<pubDate>Mon, 23 Jun 2008 20:41:21 +0000</pubDate>
		<dc:creator>qztxon</dc:creator>
				<category><![CDATA[DrProject]]></category>
		<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://qzdrproject.wordpress.com/?p=32</guid>
		<description><![CDATA[The current design for an improved role editor is still in prototype, but this is what it looks like:

The implementation of role removal is problematic, which I will be illustrating.
Upon pressing the Remove button, this confirmation form is unhidden using JavaScript:

After pressing OK, the form is submitted back onto the same page. The user is [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=qzdrproject.wordpress.com&blog=3765766&post=32&subd=qzdrproject&ref=&feed=1" />]]></description>
			<content:encoded><![CDATA[<div class='snap_preview'><br /><p>The current design for an improved role editor is still in prototype, but this is what it looks like:</p>
<p><a href="http://qzdrproject.files.wordpress.com/2008/06/delete-role-select.png"><img class="alignnone size-medium wp-image-33" src="http://qzdrproject.files.wordpress.com/2008/06/delete-role-select.png?w=300&#038;h=175" alt="Selecting a role to delete" width="300" height="175" /></a></p>
<p>The implementation of role removal is problematic, which I will be illustrating.</p>
<p>Upon pressing the Remove button, this confirmation form is unhidden using JavaScript:</p>
<p><a href="http://qzdrproject.files.wordpress.com/2008/06/delete-role-confirm.png"><img class="alignnone size-medium wp-image-36" src="http://qzdrproject.files.wordpress.com/2008/06/delete-role-confirm.png?w=300&#038;h=176" alt="Confirming delete role" width="300" height="176" /></a></p>
<p>After pressing OK, the form is submitted back onto the same page. The user is redirected to another page (admin?action=remove_role) if the role is still in use:</p>
<p><a href="http://qzdrproject.files.wordpress.com/2008/06/delete-role-further-actions.png"><img class="alignnone size-medium wp-image-37" src="http://qzdrproject.files.wordpress.com/2008/06/delete-role-further-actions.png?w=300&#038;h=126" alt="Reassign roles before removing" width="300" height="126" /></a></p>
<p>Otherwise the user gets a reloaded copy of the original page (admin?action=edit_roles):</p>
<p><a href="http://qzdrproject.files.wordpress.com/2008/06/delete-role-success.png"><img class="alignnone size-medium wp-image-38" src="http://qzdrproject.files.wordpress.com/2008/06/delete-role-success.png?w=293&#038;h=209" alt="Successfully deleted role" width="293" height="209" /></a></p>
<p>There are a number of problems with this implementation:</p>
<ul>
<li>On the server, the pages for &#8220;action=edit_roles&#8221; and &#8220;action=remove_roles&#8221; are in separate files. Looking at remove_roles, it is not immediately obvious that it needs to process form data from edit_roles.</li>
<li>When the edit_roles page redirects to the remove_roles page, all the form data is lost; the browser issues a fresh request to remove_roles. The remove_roles page gets the role in question through the URL, e.g. action=remove_roles&amp;role=viewer. This is not scalable to a large number of fields that must be preserved in a redirect.</li>
<li>If the role to be removed is still in use by some memberships, then after the user hits the confirmational OK button, he gets the reassignment page but the role is not yet removed. At the cost of extra complexity, this can be resolved by embedding the &#8220;which roles can be removed immediately?&#8221; information on the edit_roles page, so that JavaScript knows when the confirmation should be suppressed.</li>
<li>The DrProject web interface typically shows acknowledgement messages for administrative commands. So if I make the role removal subform submit to remove_roles, then it would redirect back to edit_roles if the role was immediately removable. But the page would also need to pass the name of the deleted role back to edit_roles so that it can display the acknowledgement message.</li>
</ul>
<p>One way to eliminate the redirects is to have all the possibly displayed forms put into one page, having the server cue the appropriate form on demand. This idea suffers from excessive complexity.</p>
<p>Another approach is to use AJAX techniques so that the browser does not move between pages at all.</p>
<p>Mixing Web 1.0 techniques and Web 2.0 techniques can result in more problems than using either set of techniques exclusively.</p>
<img alt="" border="0" src="http://feeds.wordpress.com/1.0/categories/qzdrproject.wordpress.com/32/" /> <img alt="" border="0" src="http://feeds.wordpress.com/1.0/tags/qzdrproject.wordpress.com/32/" /> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/qzdrproject.wordpress.com/32/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/qzdrproject.wordpress.com/32/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/qzdrproject.wordpress.com/32/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/qzdrproject.wordpress.com/32/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/qzdrproject.wordpress.com/32/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/qzdrproject.wordpress.com/32/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/qzdrproject.wordpress.com/32/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/qzdrproject.wordpress.com/32/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/qzdrproject.wordpress.com/32/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/qzdrproject.wordpress.com/32/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=qzdrproject.wordpress.com&blog=3765766&post=32&subd=qzdrproject&ref=&feed=1" /></div>]]></content:encoded>
			<wfw:commentRss>http://qzdrproject.wordpress.com/2008/06/23/dumb-redirects-interact-poorly-with-forms/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
	
		<media:content url="" medium="image">
			<media:title type="html">qztxon</media:title>
		</media:content>

		<media:content url="http://qzdrproject.files.wordpress.com/2008/06/delete-role-select.png?w=300" medium="image">
			<media:title type="html">Selecting a role to delete</media:title>
		</media:content>

		<media:content url="http://qzdrproject.files.wordpress.com/2008/06/delete-role-confirm.png?w=300" medium="image">
			<media:title type="html">Confirming delete role</media:title>
		</media:content>

		<media:content url="http://qzdrproject.files.wordpress.com/2008/06/delete-role-further-actions.png?w=300" medium="image">
			<media:title type="html">Reassign roles before removing</media:title>
		</media:content>

		<media:content url="http://qzdrproject.files.wordpress.com/2008/06/delete-role-success.png?w=293" medium="image">
			<media:title type="html">Successfully deleted role</media:title>
		</media:content>
	</item>
		<item>
		<title>HTML ought to have nested forms</title>
		<link>http://qzdrproject.wordpress.com/2008/06/23/html-ought-to-have-nested-forms/</link>
		<comments>http://qzdrproject.wordpress.com/2008/06/23/html-ought-to-have-nested-forms/#comments</comments>
		<pubDate>Mon, 23 Jun 2008 19:11:50 +0000</pubDate>
		<dc:creator>qztxon</dc:creator>
				<category><![CDATA[DrProject]]></category>
		<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://qzdrproject.wordpress.com/?p=34</guid>
		<description><![CDATA[So far, the redesign of the role editor has been done like this:

The selection box on the left is a list of all the existing roles. It is an necessary piece of information that needs to be submitted for the copy, rename, and remove operations.
The four panels on the right are initially hidden (using CSS). [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=qzdrproject.wordpress.com&blog=3765766&post=34&subd=qzdrproject&ref=&feed=1" />]]></description>
			<content:encoded><![CDATA[<div class='snap_preview'><br /><p>So far, the redesign of the role editor has been done like this:</p>
<p><a href="http://qzdrproject.files.wordpress.com/2008/06/edit-role-subforms.png"><img class="alignnone size-medium wp-image-35" src="http://qzdrproject.files.wordpress.com/2008/06/edit-role-subforms.png?w=277&#038;h=300" alt="Role editor subforms" width="277" height="300" /></a></p>
<p>The selection box on the left is a list of all the existing roles. It is an necessary piece of information that needs to be submitted for the copy, rename, and remove operations.</p>
<p>The four panels on the right are initially hidden (using <abbr title="Cascading Style Sheets">CSS</abbr>). When one of the four buttons (add, copy, rename, remove) is pressed, its corresponding panel becomes visible.</p>
<p>The code for the form(s) can be designed in at least three ways, each with its own serious problems.</p>
<p>Option 0: The left side select is common to three operations, so one form should enclose all the input elements shown in the screenshot. Note that the form would contain multiple (i.e. four) submit buttons. This is not a problem because when the user clicks an OK button, the hidden value of the button is sent, so the server can distinguish which action the user intended to take.</p>
<p>The problem here is when the user presses enter in one of the text input fields. This also submits the form. But because there are multiple buttons and none of them are specifically pressed, the web browser pretends that an arbitrary (e.g. the first) button is pressed. So if a user was trying to copy a role and presses enter in the copy panel&#8217;s text field, then the server thinks the user wants to add a role and fails the operation because no name was entered for the add operation.</p>
<p>Option 1: Put each of the four panels in its own form. Use JavaScript to copy the select&#8217;s state onto a hidden field in each form. Already, this smells like a hack. This is the approach that is currently implemented.</p>
<p>Problems with this idea include possible desynchronization between the select and hidden fields, and mandating the use of JavaScript.</p>
<p>Option 2: Instead of having four panels, just have one. Use JavaScript <abbr title="Document Object Model">DOM</abbr> manipulation to change the panel&#8217;s contents appropriately for each action. Use a hidden field (updated by JavaScript) inform the server which action the user intended to perform.</p>
<p>Again, this mandates the use of JavaScript, and <abbr title="Document Object Model">DOM</abbr> manipulation is more difficult than declaring the forms in HTML.</p>
<p>The ideal solution would be for HTML to support nested forms. (If you look at the authoritative page on <a href="http://www.w3.org/TR/html401/interact/forms.html">HTML forms</a> and squint at the <abbr title="Document Type Declaration">DTD</abbr> snippet hard enough, you&#8217;ll see that form elements are forbidden to nest.) In this case, everything (the select and the 4 panels) would be in a form, and each panel would be in its own subform. When a user presses enter in one of the text fields, its enclosing subform is submitted, along with all the fields in the parent form – but not the fields in sibling forms.</p>
<img alt="" border="0" src="http://feeds.wordpress.com/1.0/categories/qzdrproject.wordpress.com/34/" /> <img alt="" border="0" src="http://feeds.wordpress.com/1.0/tags/qzdrproject.wordpress.com/34/" /> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/qzdrproject.wordpress.com/34/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/qzdrproject.wordpress.com/34/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/qzdrproject.wordpress.com/34/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/qzdrproject.wordpress.com/34/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/qzdrproject.wordpress.com/34/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/qzdrproject.wordpress.com/34/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/qzdrproject.wordpress.com/34/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/qzdrproject.wordpress.com/34/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/qzdrproject.wordpress.com/34/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/qzdrproject.wordpress.com/34/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=qzdrproject.wordpress.com&blog=3765766&post=34&subd=qzdrproject&ref=&feed=1" /></div>]]></content:encoded>
			<wfw:commentRss>http://qzdrproject.wordpress.com/2008/06/23/html-ought-to-have-nested-forms/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
	
		<media:content url="" medium="image">
			<media:title type="html">qztxon</media:title>
		</media:content>

		<media:content url="http://qzdrproject.files.wordpress.com/2008/06/edit-role-subforms.png?w=277" medium="image">
			<media:title type="html">Role editor subforms</media:title>
		</media:content>
	</item>
	</channel>
</rss>