<?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>Ikanobori Weblog</title>
	<atom:link href="http://ikanobori.jp/weblog/feed/" rel="self" type="application/rss+xml" />
	<link>http://ikanobori.jp/weblog</link>
	<description>About my stuff.</description>
	<lastBuildDate>Sat, 01 May 2010 23:47:40 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9.2</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>How to learn Python</title>
		<link>http://ikanobori.jp/weblog/2010/05/02/how-to-learn-python/</link>
		<comments>http://ikanobori.jp/weblog/2010/05/02/how-to-learn-python/#comments</comments>
		<pubDate>Sat, 01 May 2010 23:41:28 +0000</pubDate>
		<dc:creator>ikanobori</dc:creator>
				<category><![CDATA[Python]]></category>

		<guid isPermaLink="false">http://ikanobori.jp/weblog/?p=158</guid>
		<description><![CDATA[People often ask me how they can go about learning Python. It seems a lot of people want to learn a new language.
These people are easily separable in two distinct groups. Those with prior programming experience and those without. I have made that same distinction in this blogpost.

No prior experience
If you have no prior experience [...]]]></description>
			<content:encoded><![CDATA[<p>People often ask me how they can go about learning Python. It seems a lot of people want to learn a new language.</p>
<p>These people are easily separable in two distinct groups. Those with prior programming experience and those without. I have made that same distinction in this blogpost.<br />
<span id="more-158"></span><br />
<strong>No prior experience</strong><br />
If you have no prior experience in programming it is very important to realize that programming has a steep learning curve. The basic principles (variable assignment, conditionals and loops) are often easy to understand but getting to know the ideas behind solutions to everyday problems often takes a lot of time. Don&#8217;t worry, if you persist there will come a moment of enlightenment, this moment is bliss.</p>
<p>I strongly suggest that you don&#8217;t start out badgering on your own. A good start is the <a href="http://openbookproject.net/thinkcs/python/english2e/index.html">How to Think Like a Computer Scientist</a> book which is freely available on the internet.</p>
<p>Another good start is the <a href="http://www.highercomputingforeveryone.com/">Higher Computing For Everyone</a> website made by Carl Herold. It is focused more on the C language but it gets you down on the fundamentals in a good way.</p>
<p><strong>Prior experience</strong><br />
If you have prior programming experience then the first step is to get to know Python&#8217;s type system, <a href="http://www.cafepy.com/article/python_types_and_objects/python_types_and_objects.html">OO system</a> and it&#8217;s <a href="http://docs.python.org/tutorial/stdlib.html">stdlib</a>. Also, keep in mind that in Python indenting is part of the syntax. </p>
<p>After you have gotten those out of the way it is time to start working on some features your previous language might not know, or might call/implement differently.</p>
<p>Take a look at <a href="http://docs.python.org/tutorial/datastructures.html#list-comprehensions">list comprehensions</a>, <a href="http://docs.python.org/tutorial/modules.html">generators</a> and how to create your own <a href="http://docs.python.org/tutorial/modules.html">modules</a>.</p>
<p>This is off course flying through Python at lightspeed. I strongly suggest you read the whole <a href="http://docs.python.org/tutorial/">Python tutorial</a> which is fully geared towards programmers with previous experience so you can learn all the intricacies.</p>
<p>Good luck! </p>
]]></content:encoded>
			<wfw:commentRss>http://ikanobori.jp/weblog/2010/05/02/how-to-learn-python/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>The state of bpython</title>
		<link>http://ikanobori.jp/weblog/2010/03/28/the-state-of-bpython/</link>
		<comments>http://ikanobori.jp/weblog/2010/03/28/the-state-of-bpython/#comments</comments>
		<pubDate>Sun, 28 Mar 2010 21:59:57 +0000</pubDate>
		<dc:creator>ikanobori</dc:creator>
				<category><![CDATA[Python]]></category>

		<guid isPermaLink="false">http://ikanobori.jp/weblog/?p=154</guid>
		<description><![CDATA[As some of you might know I am an active contributor to bpython. Hence my last two posts about that project.
You might also know I maintain the website for bpython. A more hidden fact might be that I like my statistics. I have decided to share those statistics about bpython with you as to give [...]]]></description>
			<content:encoded><![CDATA[<p>As some of you might know I am an active contributor to <a href="http://bpython-interpreter.org">bpython</a>. Hence my last two posts about that project.</p>
<p>You might also know I maintain the website for bpython. A more hidden fact might be that I like my statistics. I have decided to share those <a href="http://bpython-interpreter.org/webalizer">statistics</a> about bpython with you as to give some insight on how much you might expect from a small open source project.<br />
<span id="more-154"></span><br />
These statistics only reflect the traffic being directed towards the server where the bpython domain runs on (and, coincidentally, the <a href="http://bpaste.net">bpaste</a> domain). bpython is also available in many package managers (debian, ubuntu, freebsd, gentoo, to name a few). Those repositories do not cause a request to be served by the server.</p>
<p>Let me start with a big number, over the time bpython has been hosted by me it has been downloaded in excess of 25 000 times. I started hosting the website in june 2009 so that equates to a little over 2 500 downloads per month, or 80 downloads per day. This number is the only number I can confirm as I do have very little insight in installations being done through package managers (<a href="http://popcon.debian.org/">popcon</a> offers little relief). However, I need to be honest, these numbers do not include recurrent downloads people do for upgrading their package. They do count the installations done through PyPi (easy_install, pip) as those just look up the package on our server.</p>
<p>We currently have a little over 4 500 pastes on bpaste in the six months that has been online. Over the past nine months we have had over 70 000 visitors on our website who transferred a total of 100 GB. Most of the traffic due to Bob&#8217;s screencast.</p>
<p>I am extremely pleased with these numbers, I just wished I could have a bit more insight in our current installation base. I don&#8217;t know how many people currently have bpython installed, or how many removed it again.</p>
<p>A fun thing to share with you people might be this graphic, depicting what a featuring on <a href="http://reddit.com/">Reddit</a>’s programming front page will do for your visitor count.</p>
<p><img src="http://bpython-interpreter.org/webalizer/daily_usage_200907.png" alt="Webalizer." /></p>
]]></content:encoded>
			<wfw:commentRss>http://ikanobori.jp/weblog/2010/03/28/the-state-of-bpython/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Running bpython on windows (with GTK)</title>
		<link>http://ikanobori.jp/weblog/2009/12/30/running-bpython-on-windows-with-gtk/</link>
		<comments>http://ikanobori.jp/weblog/2009/12/30/running-bpython-on-windows-with-gtk/#comments</comments>
		<pubDate>Wed, 30 Dec 2009 16:05:07 +0000</pubDate>
		<dc:creator>ikanobori</dc:creator>
				<category><![CDATA[Python]]></category>

		<guid isPermaLink="false">http://ikanobori.jp/weblog/?p=149</guid>
		<description><![CDATA[An often requested feature for bpython is windows compatibility. Because bpython uses curses to draw its interface for the command line this is a difficult feature to satisfy. There are off course curses ports for windows but curses as is is a often a mess and hard to code for (edge cases and all) and [...]]]></description>
			<content:encoded><![CDATA[<p>An often requested feature for <a href="http://bpython-interpreter.org">bpython</a> is windows compatibility. Because bpython uses curses to draw its interface for the command line this is a difficult feature to satisfy. There are off course curses ports for windows but curses as is is a often a mess and hard to code for (edge cases and all) and having to support multiple (or even just one) port with a slightly different interpretation is a lot of work.<span id="more-149"></span></p>
<p>However, with bpython 0.9.6 there is a solution. We don&#8217;t build official windows packages just yet, but for the adventurous I have written down a guide in this blog post on how to get bpython.gtk_ to run on a windows machine. As of 0.9.6 the GTK part of bpython is still in its early days, its baby steps.</p>
<p>There is currently no support for hotkeys, there is no really fancy interface. However, it does have a nice icon, it has a beautiful dropdown box for the autocompletion and it supports your theme of preference. In the feature all the minor points will be resolved and more features added as development progresses.</p>
<p>Anyway, lets get down to the nitty-gritty.</p>
<p>To install bpython on a windows machine you need an installation of python + gtk, I could copy the page I followed to do this but I will not do that. I will just link you, if you follow <a href="http://www.pygtk.org/downloads.html">this page</a> you can then come back here.</p>
<p>You&#8217;ll also need to install pygments from <a href="http://pygments.org/download/">their website</a>.</p>
<p>After you have installed a full version of gtk, gobject etc. the best way to proceed is to install a <a href="http://ikanobori.jp/storage/bpython-0.9.6-win-unofficial.tar.gz">minor alteration of the bpython 0.9.6</a> version. I assume you already have setuptools installed on your windows box (for the pygments install) so you can just download the <a href="http://ikanobori.jp/storage/bpython-0.9.6-win-unofficial.tar.gz">linked file</a> and do a setup.py install.</p>
<p>After this all you need to do is make a shortcut to the file created by setuptools (the usual place is C:\PythonXX\Scripts\bpython-gtk.exe) somewhere where you find it handy.</p>
<p>Expect bugs, problems and strange stuff happening in the window (including lots of noise in the cmd-window). Report anything that seems to be a veritable bug at our <a href="http://bitbucket.org/bobf/bpython">issue tracker</a>.</p>
<p>Good luck (and a screenshot):</p>
<p><img src="http://i.imgur.com/hpTNx.png" alt="bpython.gtk_ on windows." /></p>
]]></content:encoded>
			<wfw:commentRss>http://ikanobori.jp/weblog/2009/12/30/running-bpython-on-windows-with-gtk/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>A preview to bpython 0.9.6</title>
		<link>http://ikanobori.jp/weblog/2009/12/28/a-preview-to-bpython-0-9-6/</link>
		<comments>http://ikanobori.jp/weblog/2009/12/28/a-preview-to-bpython-0-9-6/#comments</comments>
		<pubDate>Mon, 28 Dec 2009 14:06:49 +0000</pubDate>
		<dc:creator>ikanobori</dc:creator>
				<category><![CDATA[Python]]></category>

		<guid isPermaLink="false">http://ikanobori.jp/weblog/?p=141</guid>
		<description><![CDATA[Most of the people reading this blog might know I am a contributor to bpython. bpython is an interactive python repl looking to stay as close to the vanilla python repl as possible.
For this project I contribute code, I created, maintain and host their website and write the documentation.
For the 0.9.6 release a lot of [...]]]></description>
			<content:encoded><![CDATA[<p>Most of the people reading this blog might know I am a contributor to <a href="http://bpython-interpreter.org">bpython</a>. bpython is an interactive python repl looking to stay as close to the vanilla python repl as possible.</p>
<p>For this project I contribute code, I created, maintain and host their <a href="http://bpython-interpreter.org">website</a> and write the <a href="http://docs.bpython-interpreter.org">documentation</a>.</p>
<p>For the 0.9.6 release a lot of bpython has changed and a lot has been added. I am writing this post as a preview to the now upcoming release of bpython 0.9.6. Let&#8217;s go over some of the more notable changes one by one.<span id="more-141"></span></p>
<p><strong>Completion</strong><br />
Previous versions of bpython have always showed the __magic__ and _convention functions in front of the &#8216;real&#8217; methods and attributes. In the new release you will find that methods/attributes starting with a _ are filtered out unless you explicitly type a _. This has been a much requested feature and is gladly provided for now.</p>
<p>Andreas was kind enough to add backwards cycling through the completion list by adding a shift-tab shortcut.</p>
<p><strong>Dedentation</strong><br />
When you are in an indented block bpython will now automatically dedent after a few empty lines (default is 2, but this is configurable) so you don&#8217;t need to explicitly hit backspace any more.</p>
<p><strong>PEP-8</strong><br />
I have checked the source code with <a href="http://github.com/cburroughs/pep8.py">pep8.py</a> and fixed all non-conformations so bpython should now be fully conform PEP-8.</p>
<p><strong>Themes</strong><br />
There is now a (very minimal) <a href="http://bpython-interpreter.org/themes">section on user-themes</a> on the bpython website. If you have any others, please email them to me or give us a general heads up through the mailing list/IRC.</p>
<p><strong>GTK</strong><br />
Andreas has been working on a GTK version of bpython for a while now and we feel confident enough to release it together with 0.9.6 so people can start to use it. bpython will feature a bpython-gtk to run bpython in a nice GTK window.</p>
<p><strong>And more</strong><br />
A lot of bugs have been fixed, some other minor features have been added. Most notably this will be a very big release. Over 50 commits, more time between the releases then previous releases and a huge set of features (GTK, man!).</p>
<p>What are we waiting for with the release? There are a few thing we need to sort out before the release (how do we package bpython and bpython-gtk separately if we need to at all, etc) but a release will follow soon.</p>
<p>Furthermore I have some statistics for you.</p>
<p>bpython was downloaded over 1100 times the last month. We get over 650 unique visitors a day and our screencast is being watched 2000 times a month.</p>
]]></content:encoded>
			<wfw:commentRss>http://ikanobori.jp/weblog/2009/12/28/a-preview-to-bpython-0-9-6/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>#python mentality</title>
		<link>http://ikanobori.jp/weblog/2009/10/24/python-mentality/</link>
		<comments>http://ikanobori.jp/weblog/2009/10/24/python-mentality/#comments</comments>
		<pubDate>Sat, 24 Oct 2009 00:09:40 +0000</pubDate>
		<dc:creator>ikanobori</dc:creator>
				<category><![CDATA[Python]]></category>

		<guid isPermaLink="false">http://ikanobori.jp/weblog/?p=138</guid>
		<description><![CDATA[#python is an IRC channel on the Freenode network. IRC is one of the first lines of support for any large opensource project. I put it next to the mailing lists on the ladder of importance.
At the time of this writing #python features 732 distinct nicknames being one of the larger channels on the Freenode [...]]]></description>
			<content:encoded><![CDATA[<p>#python is an IRC channel on the Freenode network. IRC is one of the first lines of support for any large opensource project. I put it next to the mailing lists on the ladder of importance.</p>
<p>At the time of this writing #python features 732 distinct nicknames being one of the larger channels on the Freenode network.</p>
<p>Anyway, #python is a ‘special’ channel. There is a specific set of rules which make the channel a maintainable and live-able place.<span id="more-138"></span>Anyone who joins the channel is at first confronted with:</p>
<p><code>-!- Topic for #python: NO LOL | http://pound-python.org/ | It's too early to use Python 3.x | Pasting &gt; 3 lines? Pastebin: http://paste.pocoo.org/ | Tutorial: http://docs.python.org/tut/ | FAQ: http://effbot.org/pyfaq/ | New Programmer? Read http://tinyurl.com/thinkcspy</code></p>
<p>The important part to distill from this is:</p>
<p><strong>NO LOL. </strong>This means no ‘lolspeak’, things like 1337, lol, rofl and such are often unnecessary noise. #python tries to keep the signal-to-noise ratio as low as possible. While thinking of a place where 700 people mumble senseless abbreviations all that springs to mind is a government. And nobody likes his government.</p>
<p>After that the rules are generally easy to understand. <a href="http://pound-python.org">pound-python.org</a> is a website which contains a certain subset of answers to often-asked questions on the #python channel. It is maintained through a bazaar repository on <a href="https://launchpad.net/pound-python">launchpad</a> and hosted by me. It includes a part which I originally wrote for <a href="http://python-commandments.org">python-commandments.org</a> on the how and why it is <a href="http://python-commandments.org/python3.html">too early to use Python 3.x</a>.</p>
<p>If you paste more then 3 lines of code it quickly floods the channel. If you do want to paste more then 3 lines of code, use a pastebin like the <a href="http://paste.pocoo.org">Pocoo</a> one, <a href="http://bpaste.net">bpaste</a> or <a href="http://dpaste.net">dpaste</a>.</p>
<p>The tutorials in the topic are good, most people in the channel agree on them being good, as opposed to some of the other tutorials/books which might be of lesser perceived value to an interested person.</p>
<p>Now that we have all the ‘official’ nonsense out of the way, let me tell you more about the channel.</p>
<p>#python has a loyal regular pool of about 10-25 persons. Some work at Apple, some work at Google, some have no job. All of them might be interested in your problems though not all (or any) of them might be in at the time you ask.</p>
<p>We have a peculiar way of answering questions. More often then not you might get a counter-question on the how and why you are solving a certain problem. Do not feel offended if you get such a counter-question. The person on the other end just wants to know if you are going to use the right tool for the job. The best analogy I heard to this is that you might as well be asking how to drive a nail in to a wall with a coffee mug. We want to tell you that it is easier to use the hammer and want to verify you are not using a teapot.</p>
<p>This way of answering questions helps people. It helps people more then just giving the answer and being done with it. It also fits perfectly in the Python philosophy of not repeating done work. Most ‘hard’ problems have been solved before, and have been solved in a good way. For networking, <a href="http://twistedmatrix.com/trac/">Twisted</a> is a prime example. For database wrappers <a href="http://www.sqlalchemy.org/">SQLAlchemy</a> is a prime example. It is for a reason these two are often mentioned on #python.</p>
<p>All in all, #python might seem like a hostile place, you have great idea and immediately you are being told to “Use Twisted” or that you shouldn&#8217;t be doing what you are doing at all (type checking, for instance). This is not meant as a “not wanting to help”-mentality. It is just a different kind of helping mentality. One that I like more.</p>
]]></content:encoded>
			<wfw:commentRss>http://ikanobori.jp/weblog/2009/10/24/python-mentality/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Redesign of my weblog</title>
		<link>http://ikanobori.jp/weblog/2009/10/24/redesign-of-my-weblog/</link>
		<comments>http://ikanobori.jp/weblog/2009/10/24/redesign-of-my-weblog/#comments</comments>
		<pubDate>Fri, 23 Oct 2009 23:41:51 +0000</pubDate>
		<dc:creator>ikanobori</dc:creator>
				<category><![CDATA[About]]></category>

		<guid isPermaLink="false">http://ikanobori.jp/weblog/?p=136</guid>
		<description><![CDATA[Well, I finally set my mind to it. I ‘redesigned’ my weblog. It is now even more simplistic.
Maybe this will finally make me write some more on this weblog but I can&#8217;t promise anything. The thing is probably still teaming with bugs anyway. If you find some, let me know so I can swat them.
Oh, [...]]]></description>
			<content:encoded><![CDATA[<p>Well, I finally set my mind to it. I ‘redesigned’ my weblog. It is now even more simplistic.<br />
Maybe this will finally make me write some more on this weblog but I can&#8217;t promise anything. The thing is probably still teaming with bugs anyway. If you find some, let me know so I can swat them.</p>
<p>Oh, and taking into account the intended audience for this weblog (and some statistics from my mighty server logs) I did not bother checking the Internet Explorer-family browsers just yet.</p>
]]></content:encoded>
			<wfw:commentRss>http://ikanobori.jp/weblog/2009/10/24/redesign-of-my-weblog/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>IRC stats with irssi and pisg on debian.</title>
		<link>http://ikanobori.jp/weblog/2009/05/22/irc-stats-with-irssi-and-pisg-on-debian/</link>
		<comments>http://ikanobori.jp/weblog/2009/05/22/irc-stats-with-irssi-and-pisg-on-debian/#comments</comments>
		<pubDate>Fri, 22 May 2009 14:15:53 +0000</pubDate>
		<dc:creator>ikanobori</dc:creator>
				<category><![CDATA[Debian]]></category>

		<guid isPermaLink="false">http://ikanobori.jp/weblog/?p=123</guid>
		<description><![CDATA[Regular visitors of my blog might know I&#8217;m a sucker for statistics. I just love them and I want statistics of everything I have. It makes my data insightful.
That&#8217;s why (amongst other things) I show graphs to my traffic, hits and server load prominently on my blog pages.
Other people might also know I have an [...]]]></description>
			<content:encoded><![CDATA[<p>Regular visitors of my blog might know I&#8217;m a sucker for statistics. I just love them and I want statistics of everything I have. It makes my data insightful.</p>
<p>That&#8217;s why (amongst other things) I show graphs to my traffic, hits and server load prominently on my blog pages.</p>
<p>Other people might also know I have an unhealthy appetite for the stone age chatting protocol IRC. I currently reside in 36 channels on 5 different networks.<span id="more-123"></span></p>
<p>I decided to combine the two and start logging and graphing the usage. For the graphing I use pisg, which you can get by installing it from the repositories with:</p>
<p><code>aptitude install pisg</code></p>
<p>In this example you should already have irssi and apache running. I configured irssi with the following commands:</p>
<p><code>/set autolog on<br />
/set autolog_path ~/irclogs/$tag/$0/%Y/%m/%e.txt</code></p>
<p>This makes irssi log all channels in the following format: network/channel/month/day.txt</p>
<p>I then created a pisg config:</p>
<p><code>&lt;channel="#ubuntu-offtopic"&gt;<br />
Logfile = "/home/simon/irclogs/freenode/#ubuntu-offtopic/**/**/*"<br />
Format = "irssi"<br />
Maintainer = "ikanobori"<br />
OutputFile = "/home/simon/www_data/www.ikanobori.jp/ircstats/ubuntu-offtopic.html"<br />
Network = "Freenode"<br />
&lt;/channel&gt;</code></p>
<p>I then added a cronjob with crontab -e:</p>
<p><code>1 * * * * /usr/bin/pisg -co /home/simon/irclogs/stats.cfg</code></p>
<p>Which makes pisg run every hour.</p>
<p>See the results of this specific pisg config <a href="http://ikanobori.jp/ircstats/ubuntu-offtopic.html">here</a>.</p>
<p>Oh, you also need to move the graphics file from the /usr/share/pisg/gfx directory to the directory where you are outputting your HTML so the graphs have their nice colors.</p>
]]></content:encoded>
			<wfw:commentRss>http://ikanobori.jp/weblog/2009/05/22/irc-stats-with-irssi-and-pisg-on-debian/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Optimizing a small server with Apache2, WSGI, Python, Django and Zine.</title>
		<link>http://ikanobori.jp/weblog/2009/05/05/optimizing-a-small-server-with-apache2-wsgi-python-django-and-zine/</link>
		<comments>http://ikanobori.jp/weblog/2009/05/05/optimizing-a-small-server-with-apache2-wsgi-python-django-and-zine/#comments</comments>
		<pubDate>Tue, 05 May 2009 21:38:28 +0000</pubDate>
		<dc:creator>ikanobori</dc:creator>
				<category><![CDATA[Django]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[Webservers]]></category>

		<guid isPermaLink="false">http://ikanobori.jp/weblog/?p=81</guid>
		<description><![CDATA[I&#8217;ve taken this post off of my BrutalPenetration weblog which will be discontinued in favor of this blog (with it&#8217;s own seperate category, offcourse).
The first post in this blog will be about the tools I use for the projects web application end. It took me a lot of fiddling on my Virtual Private Server which [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ve taken this post off of my BrutalPenetration weblog which will be discontinued in favor of this blog (with it&#8217;s own seperate category, offcourse).</p>
<p>The first post in this blog will be about the tools I use for the projects web application end. It took me a lot of fiddling on my Virtual Private Server which has a limited amount of memory to make it so all my different tools work without having to restart apache every half an hour because of it chewing up all memory and not being able to handle request anymore.<span id="more-81"></span></p>
<p>First the tools we use:</p>
<ul>
<li><a href="http://www.apache.org">Apache 2</a>, webserver</li>
<li><a href="http://www.sqlite.org">SQLite</a>, database</li>
<li><a href="http://www.djangoproject.com">Django</a>, for the <a href="http://edb.brutalpenetration.org">edb</a> and our <a href="http://www.brutalpenetration.org">main website</a></li>
<li><a href="http://zine.pocoo.org">Zine</a>, for our weblog</li>
<li><a href="http://trac.edgewall.org">Trac</a>, for our <a href="http://trac.brutalpenetration.org">bugtracker</a></li>
<li><a href="http://sphinx.pocoo.org">Sphinx</a>, for the creation of our <a href="http://docs.brutalpenetration.org">documentation</a></li>
</ul>
<p>I&#8217;ll skip the part about sphinx, it only creates static html and there is nothing fancy about that. It is however great software and you should really give it a try. It is what Python uses for their own documentation.</p>
<p>I use a <a href="http://www.wsgi.org/wsgi/What_is_WSGI">WSGI</a> implementation called mod_wsgi to have the Python applications be server by Apache. It took me a lot of time to have it work so that it does not take up that much memory.</p>
<p>First of all, don&#8217;t use the embedded mode of mod_wsgi if you have little memory to spare. My VPS which runs all of Brutal Penetration&#8217;s web services only has 256 MB. If you use the embedded mode every worker process Apache spawns will have the full application you are serving contained within it. This makes consecutive requests (which are handled by the same worker process) really fast and costless but if you (like I do) have a lot of different applications on the same server this also takes a lot of worker processes which each range from 50-80MB in our case.</p>
<p>Use WSGI with the daemon mode. Our configuration concerning the edb which runs on django is, concerning the mod_wsgi part, like this:</p>
<pre>WSGIDaemonProcess edb.bp threads=2 display-name=%{GROUP}
WSGIProcessGroup edb.bp

WSGIScriptAlias / /home/brutalpenetration/edb/edb.wsgi</pre>
<p>This makes WSGI only spawn 1 process with 2 threads to serve requests. Apache workers only take up little space and direct their requests to these mod_wsgi processes. This saves a considerable amount of memory. I do this for all Python applications and for now I can say this about memory usage:</p>
<ul>
<li>Trac takes up 94 MB for a process.</li>
<li>edb (Django) takes up 75 MB for a process.</li>
<li>Zine takes up 87 MB for a process.</li>
</ul>
<p>With all of those having a considerable amount of shared memory they actually use a little less. Now for some apache benchmark results, all tests run with <em>ab -n 1000 -c 10 host</em>:</p>
<h3>Trac</h3>
<pre>Time taken for tests:   69.635 seconds
Complete requests:      1000
Failed requests:        0
Write errors:           0
Total transferred:      5830000 bytes
HTML transferred:       5486000 bytes
Requests per second:    14.36 [#/sec] (mean)
Time per request:       696.348 [ms] (mean)
Time per request:       69.635 [ms] (mean, across all concurrent requests)
Transfer rate:          81.76 [Kbytes/sec] received</pre>
<h3>edb (Django)</h3>
<pre>Concurrency Level:      10
Time taken for tests:   1.588 seconds
Complete requests:      1000
Failed requests:        0
Write errors:           0
Total transferred:      1836956 bytes
HTML transferred:       1684000 bytes
Requests per second:    629.89 [#/sec] (mean)
Time per request:       15.876 [ms] (mean)
Time per request:       1.588 [ms] (mean, across all concurrent requests)
Transfer rate:          1129.96 [Kbytes/sec] received</pre>
<h3>Weblog (Zine)</h3>
<pre>Concurrency Level:      10
Time taken for tests:   49.679 seconds
Complete requests:      1000
Failed requests:        0
Write errors:           0
Total transferred:      1835002 bytes
HTML transferred:       1691000 bytes
Requests per second:    20.13 [#/sec] (mean)
Time per request:       496.788 [ms] (mean)
Time per request:       49.679 [ms] (mean, across all concurrent requests)
Transfer rate:          36.07 [Kbytes/sec] received</pre>
<p>And for comparison, a site serving only static content:</p>
<h3>Documentation</h3>
<pre>Concurrency Level:      10
Time taken for tests:   0.239 seconds
Complete requests:      1000
Failed requests:        0
Write errors:           0
Total transferred:      274274 bytes
HTML transferred:       38038 bytes
Requests per second:    4177.32 [#/sec] (mean)
Time per request:       2.394 [ms] (mean)
Time per request:       0.239 [ms] (mean, across all concurrent requests)
Transfer rate:          1118.88 [Kbytes/sec] received</pre>
<p>This pretty much concludes my blog post, I have one final tip, don&#8217;t use MySQL unless you have to. My mysqld used up 109 MB of memory which pushed everything into swap. I now use sqlite for django and zine and it works perfectly.</p>
]]></content:encoded>
			<wfw:commentRss>http://ikanobori.jp/weblog/2009/05/05/optimizing-a-small-server-with-apache2-wsgi-python-django-and-zine/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Language performance on the sum of a file.</title>
		<link>http://ikanobori.jp/weblog/2009/04/11/language-performance-on-the-sum-of-a-file/</link>
		<comments>http://ikanobori.jp/weblog/2009/04/11/language-performance-on-the-sum-of-a-file/#comments</comments>
		<pubDate>Sat, 11 Apr 2009 22:43:33 +0000</pubDate>
		<dc:creator>ikanobori</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://ikanobori.jp/weblog/?p=95</guid>
		<description><![CDATA[Well, one of my posts caused quite a bit of attention so I am revisiting the subject. I&#8217;ll start by explaining what the idea is:
 I have a text file containing numbers, a random amount of numbers per line and the numbers are of random size. Can you quickly give me a sum of all [...]]]></description>
			<content:encoded><![CDATA[<p>Well, <a href="http://ikanobori.jp/weblog/2009/04/08/python-sum-of-file-generators-vs-list-comprehensions/">one</a> of my posts caused quite a bit of attention so I am revisiting the subject. I&#8217;ll start by explaining what the idea is:</p>
<p><em> I have a text file containing numbers, a random amount of numbers per line and the numbers are of random size. Can you quickly give me a sum of all numbers? The file has to be read from stdin.</em></p>
<p>You can find the example file I used <a href="http://ikanobori.jp/storage/input_list_vs_gen.txt">here</a>.<span id="more-95"></span></p>
<p>I made a solution in Python, using generator comprehensions. However, a battle ensued in the comments to create the quickest version of this program and after a few comments about 30% was shaven off the time my Python program took. Then things took a turn, comments started dripping in of other languages. Haskell, PHP, Ruby and C amongst others were submitted.</p>
<p>Thus I have decided to create a little posting about this specific problem. Firstly I have compiled and run all the different versions and languages on my hardware and timed then. I ran every tool 10 times and averaged the result which resulted in this graph:</p>
<p>Source codes are here, however, if you think you can do any better than this please submit a link to a pastebin in the comments with some explanation and I&#8217;ll update this post and graph. I&#8217;d like for funky languages to be included as well, as long as I can compile it on my Debian server!</p>
<p>Results (scroll down for credits and source code for each language, think you can do better or have other languages? comment!):</p>
<p><img src="http://ikanobori.jp/storage/performance.png" alt="" /></p>
<ul>
<li>PHP: <strong>2.53 s</strong></li>
<li>x86 asm: <strong>0.04 s</strong></li>
<li>Ruby 1.9.1: <strong>3.59 s</strong></li>
<li>C: <strong>0.04 s</strong></li>
<li>Python: <strong>2.18 s</strong></li>
<li>Haskell: <strong>0.05 s</strong></li>
<li>gawk: <strong>1.61 s</strong></li>
<li>Perl: <strong>4.74 s</strong></li>
<li>Vala: <strong>2.01 s</strong></li>
</ul>
<p>I also ran the fastest three on a large input file. Haskell fails, giving the wrong number.</p>
<p><img class="alignnone" src="http://ikanobori.jp/storage/performancel.png" alt="" width="429" height="320" /></p>
<ul>
<li>C: <strong>2.91 s</strong></li>
<li>x86 asm: <strong>4.39 s</strong></li>
</ul>
<p>Clearly, C and Haskell reign supreme even knowing more about the processor instructions then RayNbow&#8217;s x86 solution. Python is fastest at the interpreted languages. I ran the Ruby sample on Ruby 1.8 as well which took 20ish seconds, Ruby is surely stepping up it&#8217;s game, speedwise, still lacking a bit behind PHP though.</p>
<p><strong>C (luite) (gcc -O2)</strong>:</p>
<pre>#include &lt;stdio.h&gt;
#include &lt;stdint.h&gt;

int main(int argc, char** argv) {
  uint64_t sum=0;
  char buf[8192];
  int cur=0;
  int i,j;
  while((i=fread(buf,1,8192,stdin))&gt;0) {
    for(j=0;j&lt;i;j++) {
      char c = buf[j];
      if(c &gt;= '0' &amp;&amp; c &lt;= '9') {
  cur = (cur*10)+c-48;
      } else {
  sum+=cur;
  cur=0;
      }
    }
  }
  sum+=cur;
  printf("total: %llu\n", sum); /* what is the correct format type for uint64_t? */
}</pre>
<p><strong>Haskell (Don Stewart)</strong>:</p>
<div class="highlight">
<pre><span id="li-3684-1"><span class="cm">{-# LANGUAGE BangPatterns #-}</span>
</span><span id="li-3684-2"><span class="c1">--</span>
</span><span id="li-3684-3"><span class="c1">-- The Computer Language Shootout</span>
</span><span id="li-3684-4"><span class="c1">-- http://shootout.alioth.debian.org/</span>
</span><span id="li-3684-5"><span class="c1">--</span>
</span><span id="li-3684-6"><span class="c1">-- A lazy bytestring solution</span>
</span><span id="li-3684-7"><span class="c1">--</span>
</span><span id="li-3684-8">
</span><span id="li-3684-9"><span class="kr">import</span> <span class="k">qualified</span> <span class="nn">Data.ByteString.Char8</span> <span class="k">as</span> <span class="n">S</span>
</span><span id="li-3684-10">
</span><span id="li-3684-11"><span class="nf">main</span> <span class="ow">=</span> <span class="kr">do</span>
</span><span id="li-3684-12">    <span class="n">putStr</span> <span class="s">"Grand total "</span>
</span><span id="li-3684-13">    <span class="n">print</span> <span class="o">.</span> <span class="n">go</span> <span class="mi">0</span> <span class="o">=&lt;&lt;</span> <span class="kt">S</span><span class="o">.</span><span class="n">getContents</span>
</span><span id="li-3684-14">  <span class="kr">where</span>
</span><span id="li-3684-15">    <span class="n">go</span> <span class="o">!</span><span class="n">n</span> <span class="o">!</span><span class="n">s</span> <span class="ow">=</span> <span class="kr">case</span> <span class="kt">S</span><span class="o">.</span><span class="n">readInt</span> <span class="n">s</span> <span class="kr">of</span> <span class="c1">-- lazily reads current line</span>
</span><span id="li-3684-16">                    <span class="kt">Nothing</span>     <span class="ow">-&gt;</span> <span class="n">n</span>
</span><span id="li-3684-17">                    <span class="kt">Just</span> <span class="p">(</span><span class="n">k</span><span class="p">,</span><span class="n">t</span><span class="p">)</span>  <span class="ow">-&gt;</span> <span class="n">go</span> <span class="p">(</span><span class="n">n</span><span class="o">+</span><span class="n">k</span><span class="p">)</span> <span class="p">(</span><span class="kt">S</span><span class="o">.</span><span class="n">tail</span> <span class="n">t</span><span class="p">)</span>
</span><span id="li-3684-18">
</span><span id="li-3684-19">
</span><span id="li-3684-20"><span class="cm">{-</span>
</span><span id="li-3684-21">
</span><span id="li-3684-22"><span class="cm">-- Important: turn on optimizations:</span>
</span><span id="li-3684-23">
</span><span id="li-3684-24"><span class="cm">$ ghc -O2 --make A.hs             </span>
</span><span id="li-3684-25"><span class="cm">[1 of 1] Compiling Main             ( A.hs, A.o )</span>
</span><span id="li-3684-26"><span class="cm">Linking A ...</span>
</span><span id="li-3684-27">
</span><span id="li-3684-28"><span class="cm">$ cksum input_list_vs_gen.txt </span>
</span><span id="li-3684-29"><span class="cm">2913999841 17293232 input_list_vs_gen.txt</span>
</span><span id="li-3684-30">
</span><span id="li-3684-31"><span class="cm">$ du -hs input_list_vs_gen.txt </span>
</span><span id="li-3684-32"><span class="cm">17M input_list_vs_gen.txt</span>
</span><span id="li-3684-33">
</span><span id="li-3684-34"><span class="cm">$ time ./A &lt; input_list_vs_gen.txt </span>
</span><span id="li-3684-35"><span class="cm">Grand total 17677692470</span>
</span><span id="li-3684-36"><span class="cm">./A &lt; input_list_vs_gen.txt  0.19s user 0.06s system 98% cpu 0.254 total</span>
</span><span id="li-3684-37">
</span><span id="li-3684-38"><span class="cm">-}</span></span></pre>
</div>
<p><strong>PHP (John Piasetzki)</strong>:</p>
<pre>while($line = fgets(STDIN))
  $s += array_sum(explode(' ',$line));
echo $s;</pre>
<p><strong>Python (Pythoneer):</strong></p>
<pre>#!/usr/bin/env/python
import sys
from itertools import imap

print sum(sum(imap(int, line.split())) for line in sys.stdin)</pre>
<p><strong>Ruby (Thomas Hurst)</strong>:</p>
<pre>#!/usr/bin/env ruby
total = 0
STDIN.each_line {|line| line.split(" ").each {|x| total += x.to_i } }
puts "Grand total: #{total}"</pre>
<p><strong>x86 asm (James Block)</strong>:</p>
<pre>; for NASM, a 386 or better, and a 2.6-series Linux kernel
; it should run fine on a 64-bit system with appropriate flags for NASM
; assemble with nasm -f elf FILENAME.asm &amp;&amp; ld FILENAME.o -o OUTPUTFILENAME
; run as ./OUTPUTFILENAME &lt; INPUT_NUMBERS.txt
; expect weirdness with nonconforming input. this is pure assembly, you know
; each input number should be at most 32 bits, and the sum at most 64 bits

buffersize equ (1&lt;&lt;16)	;use 64kB chunks; can be set to any value
			;64kB is fastest on this old Willamette P4

section .data
	message: db "Grand total:"
	printbuffer: times 23 db 0x20
	dw 0x0A
	msglen equ $ - message

section .text
	global _start

_start:
	;we want to read a bunch of numbers from STDIN
	;we'll do this by allocating memory with mmap()
	;and then reading stdin with read()
	;
	;mmap signature:
	; void* mmap(void* start, size_t length, int prot, int flags,
	;	int fd, off_t offset);
	; (defined in &lt;sys/mman.h&gt;)
	;
	;arguments:
	; start - pass 0, usually ignored
	; length - pass $BIGNUM to allocate a $BIGNUM chunk
	; prot - pass PROT_READ | PROT_WRITE (0x01|0x02)
	; flags - pass MAP_PRIVATE (0x02) | MAP_ANONYMOUS (0x20)
	; fd - pass anything (-1)
	; offset - pass anything
	;
	; linux calling convention: 6-arg syscalls use the stack
	;   push arguments in REVERSE order
	;
	; system call number goes in eax:
	;  exit:	1
	;  read:	3
	;  write:	4
	;  mmap:	90
	;  munmap:	91

	mov esi, buffersize	;store buffer size in esi

	push dword 0	;offset
	push dword -1	;fd
	push dword 0x22	;flags - MAP_PRIVATE|MAP_ANONYMOUS
	push dword 0x03	;prot - PROT_READ|PROT_WRITE
	push dword esi	;allocation size
	push dword 0	;start
	mov eax, 90
	mov ebx, esp

	int 80h
	add esp, (4*6)	;clean up the refuse from calling mmap()

	;now eax holds the start address for our memory! yay!
	;let's put it in ebp instead, since ebp isn't good for much else
	mov ebp, eax

	;now let's read() in the data from stdin
	;read() signature:
	; ssize_t read(int fd, void* buf, size_t count)
	;3-arg syscalls pass arguments in registers, so
	;this one's much easier than mmap():

	mov ecx, eax
	mov ebx, 0
	mov eax, 3
	mov edx, esi
	int 80h

	;accumulate in the traditional pairing edx:eax
	;let ecx index our position in the memory block

	;read digits into ebx, accumulate into numbers in edi
	; then sum edi to the main accumulator, edx:eax
	; anything but a digit ends a number
	; zero byte ends all counting

	xor edx, edx
	xor eax, eax
	xor ecx, ecx
	dec ecx

readdigit:
	xor edi, edi
readdigit_lp:
	xor ebx, ebx
	inc ecx
	cmp ecx, esi
	je readmore
gotmore:mov bl, byte [ebp+ecx]
	test bl, bl
	jz finished_summing		;exit on zero byte

	sub bl, 48
	js next_number
	cmp bl, 9
	ja next_number	;if this is not a digit, skip it and sum

	shl edi, 1
	lea edi, [edi*4 + edi]
	add edi, ebx
	jmp readdigit_lp

next_number:
	add eax, edi
	jnc readdigit
	inc edx
	jmp readdigit

readmore:
	mov esp, eax
	mov eax, 3
	xor ebx, ebx
	mov ecx, ebp
	xchg edx, esi
	int 80h

	;if we didn't fill the whole buffer, stick a zero byte after the
	; bit we *did* read, to ensure proper termination of the loop

	cmp eax, edx
	je readcleanup
	mov byte [ebp+eax+1], 00
readcleanup:
	xor ecx, ecx
	xchg edx, esi
	mov eax, esp
	jmp gotmore

finished_summing:
	;edx:eax contains the 64-bit sum
	;now we have to print it
	;the following is an EXTREMELY ugly printf(%llu) substitute

	mov ecx, (printbuffer+22)
	mov ebp, 10
	mov esp, 429496729

printlp64:
	;if we can bail on this horrid 64-bit print loop
	; and use a much saner 32-bit version,
	; then, damn it, EXIT NOW
	test edx, edx
	jz printlp32

	;algorithm (64-bit divmod): let W = 2**32, Z = X + Y*W
	; (i.e., X is eax and Y is edx)
	; then let M = 10 (modulus) and define
	; X divmod M = (x_D, x_M)   (the definition of divmod:
	; Y divmod M = (y_D, y_M)   (quotient, remainder))
	; W divmod M = (W_D, W_M)
	;
	; let u = x_M + y_M * W_M and calculate
	; u divmod M = (u_D, u_M)
	;
	; then the following is true:
	; Z divmod M = (y_D * W + x_D + y_M*W_D + u_D, u_M)
	;
	; the following pile of junk implements the above
	;  (and allows for overflow in a couple places)

	mov edi, eax
	mov eax, edx
	xor edx, edx
	div ebp
	lea ebx, [edx*3]
	shl ebx, 1
	mov esi, eax
	mov eax, edx
	mul esp
	;edx:eax has y_M*W_D, ebx has y_M*W_M, edi has x, esi has y_D
	add esi, edx
	xor edx, edx
	xchg eax, edi
	div ebp
	;eax has x_D, edx has x_M, esi has y_D, edi has y_M*W_D
	add ebx, edx	;ebx has u
	add edi, eax
	xor edx, edx
	mov eax, ebx
	div ebp
	;eax has u_D, edx has u_M
	add dl, 0x30
	mov byte [ecx], dl
	dec ecx
	mov edx, esi
	add eax, edi
	jnc printlp64
	inc edx
	jmp printlp64

printlp32:
	div ebp
	add dl, 0x30
	mov byte [ecx], dl
	dec ecx
	xor edx, edx
	test eax, eax
	jnz printlp32

EXIT:
	mov eax, 4
	mov ebx, 1
	mov ecx, message
	mov edx, msglen
	int 80h

	mov eax, 1
	mov ebx, 0
	int 80h</pre>
<p><strong>Perl (Michael Pyne)</strong>:</p>
<pre>#!/usr/bin/env perl

use strict;

my $sum = 0;
while(&lt;STDIN&gt;) {
my @nums = split(' ');
foreach my $num (@nums) { $sum += $num; }
}

print "$sum\n";</pre>
<p><strong>Gawk (Eric Wong)</strong>:</p>
<pre>gawk 'END { printf "%d\n", n } { for (i=NF;i&gt;0;--i) n += $i}'</pre>
<p><strong>Vala (snuxoll)</strong>:</p>
<pre>using GLib;

namespace snuxoll {
    class StdinReader : Object {

        public StdinReader () {

        }

        public bool eof() {
            return stdin.eof();
        }

        public string? read_line() {
            var line = new StringBuilder();
            var buffer = new char[1024];
            while ( ( !line.str.has_suffix ("\n") ) || this.eof() ) {
                string chunk = stdin.gets(buffer);
                if (chunk != null) {
                    line.append(chunk);
                } else {
                  return null;
                }
            }
            return line.str;
        }

    }
}

// start other file

using GLib;
using snuxoll;

class SumApplication : Object {

    private uint64 total { get; set; }

    public SumApplication() {
        this.total = 0;
    }

    public void run() {
        var reader = new StdinReader();
        while ( !stdin.eof() ) {
            var line = reader.read_line();
            if ( line != null ) {
              var nums = line.strip().split(" ");
              foreach(string num in nums) {
                    this.total += num.to_int();
                }
            }
        }
        stdout.printf("Grand Total: %llu\n", total);
    }

    static int main(string[] args) {
        var app = new SumApplication();
        app.run();
        return 0;
    }

}</pre>
]]></content:encoded>
			<wfw:commentRss>http://ikanobori.jp/weblog/2009/04/11/language-performance-on-the-sum-of-a-file/feed/</wfw:commentRss>
		<slash:comments>88</slash:comments>
		</item>
		<item>
		<title>jQuery. Draggables, droppables. jQuery can&#8217;t recalculate the droptargets?</title>
		<link>http://ikanobori.jp/weblog/2009/04/09/jquery-draggables-droppables-jquery-cant-recalculate-the-droptargets/</link>
		<comments>http://ikanobori.jp/weblog/2009/04/09/jquery-draggables-droppables-jquery-cant-recalculate-the-droptargets/#comments</comments>
		<pubDate>Thu, 09 Apr 2009 09:31:30 +0000</pubDate>
		<dc:creator>ikanobori</dc:creator>
				<category><![CDATA[Javascript]]></category>
		<category><![CDATA[jQuery]]></category>

		<guid isPermaLink="false">http://ikanobori.jp/weblog/?p=84</guid>
		<description><![CDATA[As an avid fan of jQuery (however, not using it too much) I&#8217;ve encountered a problem I really need to solve. I am writing this post in the hopes that some of the jQuery community will pick up on this as I think it is a problem a lot of jQuery developers will need to [...]]]></description>
			<content:encoded><![CDATA[<p>As an avid fan of jQuery (however, not using it too much) I&#8217;ve encountered a problem I really need to solve. I am writing this post in the hopes that some of the jQuery community will pick up on this as I think it is a problem a lot of jQuery developers will need to solve one time or another time.</p>
<p>I will start by describing my problem. The problem concerns a large tree which is foldable, by a large tree I am talking about about 200 main nodes with each of them ≈ 5 subnodes with each subnode an arbitrary number of pages or other subnodes.<span id="more-84"></span></p>
<p>We load the sublevels using AJAX. This works fine. The tree at first is generated from XML using XSL and the outputted HTML looks like this:</p>
<pre id="line1">&lt;ul class="vline"&gt;
  &lt;<span class="start-tag">li</span><span class="attribute-name"> class</span>=<span class="attribute-value">"sep"</span>&gt;&amp;<span class="entity">nbsp;</span>&lt;/<span class="end-tag">li</span>&gt;
  &lt;<span class="start-tag">li</span><span class="attribute-value"> </span><span class="attribute-name">id</span>=<span class="attribute-value">"C697EDFA-1517-64D9-CCE728FA69AABB13" </span><span class="attribute-name">class</span>=<span class="attribute-value">"open"</span>&gt;
    &lt;<span class="start-tag">div</span><span class="attribute-name"> class</span>=<span class="attribute-value">"toggle"</span>&gt;&amp;<span class="entity">nbsp;</span>&lt;/<span class="end-tag">div</span>&gt;
    &lt;<span class="start-tag">div</span><span class="attribute-name"> class</span>=<span class="attribute-value">"label"</span>&gt;
      &lt;<span class="start-tag">a</span><span class="attribute-name"> href</span>=<span class="attribute-value">"#"</span>&gt;Loret Ipsum&lt;/<span class="end-tag">a</span>&gt;
    &lt;/<span class="end-tag">div</span>&gt;
    &lt;<span class="start-tag">div</span><span class="attribute-name"> class</span>=<span class="attribute-value">"active"</span>&gt;&lt;<span class="start-tag">a</span><span class="attribute-name"> </span><span class="attribute-name">href</span>=<span class="attribute-value">"#"</span>&gt;nl&lt;/<span class="end-tag">a</span>&gt;&lt;/<span class="end-tag">div</span>&gt;
    &lt;<span class="start-tag">ul</span><span class="attribute-name"> class</span>=<span class="attribute-value">"vline"</span>&gt;
      &lt;<span class="start-tag">li</span><span class="attribute-name"> class</span>=<span class="attribute-value">"sep"</span>&gt;&amp;<span class="entity">nbsp;</span>&lt;/<span class="end-tag">li</span>&gt;
      &lt;<span class="start-tag">li</span><span class="attribute-name"> class</span>=<span class="attribute-value">"closed" </span><span class="attribute-name">id</span>=<span class="attribute-value">"C697EE29-1517-64D9-CC87AC418D9DF2E4"</span>&gt;
        &lt;<span class="start-tag">div</span><span class="attribute-name"> class</span>=<span class="attribute-value">"toggle"</span>&gt;&amp;<span class="entity">nbsp;</span>&lt;/<span class="end-tag">div</span>&gt;
        &lt;<span class="start-tag">div</span><span class="attribute-name"> class</span>=<span class="attribute-value">"label"</span>&gt;
          &lt;<span class="start-tag">a</span><span class="attribute-value"> </span><span class="attribute-name">href</span>=<span class="attribute-value">"#"</span>&gt;Dolor sit amet&lt;/<span class="end-tag">a</span>&gt;
        &lt;/<span class="end-tag">div</span>&gt;
      &lt;/<span class="end-tag">li</span>&gt;
      &lt;<span class="start-tag">li</span><span class="attribute-name"> class</span>=<span class="attribute-value">"sep"</span>&gt;&amp;<span class="entity">nbsp;</span>&lt;/<span class="end-tag">li</span>&gt;
      &lt;<span class="start-tag">li</span><span class="attribute-name"> class</span>=<span class="attribute-value">"closed" </span><span class="attribute-name">id</span>=<span class="attribute-value">"C697EE29-1517-64D9-CC87AC418D9DF2E4"</span>&gt;
        &lt;<span class="start-tag">div</span><span class="attribute-name"> class</span>=<span class="attribute-value">"toggle"</span>&gt;&amp;<span class="entity">nbsp;</span>&lt;/<span class="end-tag">div</span>&gt;
        &lt;<span class="start-tag">div</span><span class="attribute-name"> class</span>=<span class="attribute-value">"label"</span>&gt;
          &lt;<span class="start-tag">a</span><span class="attribute-value"> </span><span class="attribute-name">href</span>=<span class="attribute-value">"#"</span>&gt;Nunc est amet&lt;/<span class="end-tag">a</span>&gt;
        &lt;/<span class="end-tag">div</span>&gt;
      &lt;/<span class="end-tag">li</span>&gt;
      &lt;<span class="start-tag">li</span><span class="attribute-name"> class</span>=<span class="attribute-value">"sep"</span>&gt;&amp;<span class="entity">nbsp;</span>&lt;/<span class="end-tag">li</span>&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li class="sep"&gt;&amp;nbsp;&lt;/li&gt;
&lt;/ul&gt;</pre>
<p>This generates a nice list. I then use selectors to make certain parts droppable (&#8216;li a&#8217;), (&#8216;.sep&#8217;) and certain parts draggable (&#8216;li&#8217;). This works fine with the default jQuery draggable/droppable. However, the default draggable/droppable is painstakingly slow. It looks like it recalculates all droptargets&#8217; positions the moment you start dragging. This causes a 1 to 2 second delay on the MacBook Pro I am developing on, I don&#8217;t even dare to think about the slower cpu&#8217;s used by clients and visitors.</p>
<p>The drop targets need to be recalculated because a user can fold/unfold nodes to their liking. If you do not update the drop targets then a folded tree will give funny results because the targets below the folded node have changed position.</p>
<p>So I ventured out to start recalculating drop targets when I fold or unfold a node. This causes a delay in the folding/unfolding in which I can show a nice AJAXish loading image which looks good to the user and obfuscates the amount of calculations being done in the background.</p>
<p>What I have tried to get this behaviour:</p>
<ul>
<li>First I started fiddling with a plugin called <a href="http://blog.threedubmedia.com/2008/08/eventspecialdrop.html">jquery.event.drop</a> and rebinding the droppable event when a node folds/unfolds. This is to no avail.</li>
<li>Second I updated my jQuery to 1.3 to use live events, this did not help but did break a lot of other existing jQuery code.</li>
</ul>
<p>I know the plugin jquery.event.drop has a setup() method which uses it&#8217;s built in method locate() to calculate all drop targets. However I just can not seem to find out how to call this setup() function again.</p>
<p>Is this just impossible in jQuery and should I build it from scratch or is there some nifty way of doing this which I am totally overlooking?</p>
<p>Also, a little excerpt from the javascript I am using right now:</p>
<pre>function create_drop_targets() {
  $('li a')
    .bind('dropstart', function(event) {
    })
    .bind('drop', function(event) {
    })
    .bind('dropend', function(event) {
    });
}</pre>
]]></content:encoded>
			<wfw:commentRss>http://ikanobori.jp/weblog/2009/04/09/jquery-draggables-droppables-jquery-cant-recalculate-the-droptargets/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
